Documentation Source Text

Check-in [6d60e5d021]
Login

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

Overview
Comment:Work on the window function documentation, including importing the new syntax diagrams.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6d60e5d0211950dddab8ea8f6ae5c79924e14f71808e724763bec028594e2b24
User & Date: drh 2018-07-06 20:43:09.462
Context
2018-07-07
17:36
Minor changes to the windows function documentation. (check-in: ff1e1e885a user: drh tags: trunk)
2018-07-06
20:43
Work on the window function documentation, including importing the new syntax diagrams. (check-in: 6d60e5d021 user: drh tags: trunk)
18:30
Update the syntax diagrams to include the new window function syntax. (check-in: f7a6a2f7c2 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to pages/windowfunctions.in.
11
12
13
14
15
16
17
18

19
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

<h1>Introduction to Window Functions</h1>

<p>A window function is a special type of SQL function for which the results
depend on the contents of a "window" of one or more contiguous rows returned
by the SELECT statement containing the window function. A window function may
only be used in the select-list or ORDER BY clause of a SELECT or sub-select
construction. The syntax for a window function is similar to that for a regular scalar SQL function except that it is followed by an OVER clause. The full

syntax is:

<codeblock>
  &lt;window-function&gt;     := &lt;function&gt;(&lt;args...&gt;) &#91;&lt;filter&gt;] OVER (&lt;window-definition&gt;)

  &lt;filter&gt;              := FILTER (WHERE &lt;expr&gt;)

  &lt;window-definition&gt;   := &#91;PARTITION BY &lt;expression-list&gt;] &#91;ORDER BY &lt;expression-list&gt;] &#91;&lt;frame-specification&gt;]

  &lt;frame-specification&gt; := ROWS|RANGE BETWEEN &lt;frame-boundary&gt; AND &lt;frame-boundary&gt;

  &lt;frame-boundary&gt;      := UNBOUNDED PRECEDING
  &lt;frame-boundary&gt;      := &lt;expr&gt; PRECEDING
  &lt;frame-boundary&gt;      := CURRENT ROW
  &lt;frame-boundary&gt;      := &lt;expr&gt; FOLLOWING
  &lt;frame-boundary&gt;      := UNBOUNDED FOLLOWING
</codeblock>


<p>For example, given:

<codeblock>
  CREATE TABLE t0(x INTEGER PRIMARY KEY, y TEXT);
  INSERT INTO t0 VALUES (1, 'aaa'), (2, 'ccc'), (3, 'bbb');
</codeblock>

<p>Then:

<codeblock>
  <i>-- The following SELECT statement returns:</i>
  <i>-- </i>
  <i>--   x | y | row_number</i>
  -----------------------
  <i>--   1 | aaa | 1         </i>
  <i>--   2 | ccc | 3         </i>
  <i>--   3 | bbb | 2         </i>
  <i>-- </i>
  SELECT x, y, row_number() OVER (ORDER BY y) AS row_number FROM t0 ORDER BY x;
</codeblock>

<p>The example above uses the special built-in window function row_number().

This function returns a monotonically increasing integer assigned to each
row in order of the the "ORDER BY" clause within the
<i>&lt;window-definition&gt;</i> (in this case "ORDER BY y"). Note that 
this does not affect the order in which results are returned to the user -

that is still governed by the ORDER BY clause attached to the SELECT
statement (in this case "ORDER BY x").

<p>Named <i>&lt;window-definitions&gt;</i> may also be added to a SELECT 
statement using a WINDOW clause and then refered to by name within window
function invocations. For example, the following SELECT statement contains
two named <i>&lt;window-definitions&gt;</i>, "win1" and "win2":

<codeblock>
  SELECT x, y, row_number() OVER <b>win1</b>, rank() OVER <b>win2</b> FROM t0 

  WINDOW <b>win1</b> AS (ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
         <b>win2</b> AS (PARTITION BY y ORDER BY x)
  ORDER BY x;
</codeblock>

<p>The WINDOW clause, when one is present, comes after any HAVING clause and
before any ORDER BY.







|
>
|

|
|
|
<

|
|
|
|
|
|
|
<
<
<

>
|






|













|
>
|

|
|
>
|


|


|


|
>







11
12
13
14
15
16
17
18
19
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

<h1>Introduction to Window Functions</h1>

<p>A window function is a special type of SQL function for which the results
depend on the contents of a "window" of one or more contiguous rows returned
by the SELECT statement containing the window function. A window function may
only be used in the select-list or ORDER BY clause of a SELECT or sub-select
construction. The syntax for a window function is similar to that for a regular
scalar SQL function except that it is followed by an OVER clause. The full
syntax is as follows:

<tcl>
RecursiveBubbleDiagram window-function-invocation
</tcl>


<p>Window function are distingished from ordinary SQL functions by the
presence of an OVER clause.  If a function invocation has an OVER clause
then it is a window function, and if lacks a OVER clause it is an ordinary
function.  Window functions might also have a FILTER
clause in between the function and the OVER clause.
Unlike ordinary functions, window functions
cannot use the DISTINCT keyword.




<p>The following simple table is used to demonstrate how window
functions work:

<codeblock>
  CREATE TABLE t0(x INTEGER PRIMARY KEY, y TEXT);
  INSERT INTO t0 VALUES (1, 'aaa'), (2, 'ccc'), (3, 'bbb');
</codeblock>

<p>An example of using window functions:

<codeblock>
  <i>-- The following SELECT statement returns:</i>
  <i>-- </i>
  <i>--   x | y | row_number</i>
  -----------------------
  <i>--   1 | aaa | 1         </i>
  <i>--   2 | ccc | 3         </i>
  <i>--   3 | bbb | 2         </i>
  <i>-- </i>
  SELECT x, y, row_number() OVER (ORDER BY y) AS row_number FROM t0 ORDER BY x;
</codeblock>

<p>The example uses the built-in window function row_number().
The row_number() window function
assigns a monotonically increasing integer to each
row in order of the the "ORDER BY" clause within the
<yynonterm>window-defn</yynonterm> (in this case "ORDER BY y"). Note that 
this does not affect the order in which results are returned from
the overall query.  The order of the final output is
is still governed by the ORDER BY clause attached to the SELECT
statement (in this case "ORDER BY x").

<p>Named <yynonterm>window-defn</yynonterm> clauses may also be added to a SELECT 
statement using a WINDOW clause and then refered to by name within window
function invocations. For example, the following SELECT statement contains
two named <yynonterm>window-defs</yynonterm> clauses, "win1" and "win2":

<codeblock>
  SELECT x, y, row_number() OVER <b>win1</b>, rank() OVER <b>win2</b> 
  FROM t0 
  WINDOW <b>win1</b> AS (ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
         <b>win2</b> AS (PARTITION BY y ORDER BY x)
  ORDER BY x;
</codeblock>

<p>The WINDOW clause, when one is present, comes after any HAVING clause and
before any ORDER BY.
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
    ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) AS group_concat FROM t1;
</codeblock>

<p> In the example above, the window frame consists of all rows between the
previous row ("1 PRECEDING") and the following row ("1 FOLLOWING"), inclusive,
where rows are sorted according to the ORDER BY clause in the

<i>&lt;window-definition&gt;</i> (in this case "ORDER BY a"). For example, the frame for the row with (a=3) consists of rows (2, 'B', 'two'), (3, 'C', 'three') and (4, 'D', 'one'). The result of group_concat(b, '.') for that row is therefore 'B.C.D'.



<p> The default <i>&lt;frame-specification&gt;</i> is:

<codeblock>
    RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
</codeblock>

<p> This means that, after sorting the rows returned by the SELECT according to

the ORDER BY clause in the &lt;window-definition&gt;, the window frame consists
of all rows between the first row and the last row with the same values as the current row for all ORDER BY expressions. This implies that rows that have the same values for all ORDER BY expressions will also have the same value for the result of the window function (as the window frame is the same). For example:





<codeblock>
  <i>-- The following SELECT statement returns:</i>
  <i>-- </i>
  <i>--   a | b | c | group_concat</i>
  -----------------------------
  <i>--   1 | A | one   | A.D.G       </i>
  <i>--   2 | B | two   | A.D.G.C.F.B.E</i>
  <i>--   3 | C | three | A.D.G.C.F   </i>
  <i>--   4 | D | one   | A.D.G       </i>
  <i>--   5 | E | two   | A.D.G.C.F.B.E</i>
  <i>--   6 | F | three | A.D.G.C.F   </i>
  <i>--   7 | G | one   | A.D.G       </i>
  <i>-- </i>
  SELECT a, b, c, 
         group_concat(b, '.') OVER (ORDER BY c) AS group_concat 
  FROM t1 ORDER BY a;
</codeblock>

<p> All of SQLite's [Aggregate Functions|aggregate functions] may be used as aggregate window
functions. It is also possible to 
[user-defined window functions|create user-defined aggregate window functions].

<h2>Frame Specifications</h2>




<p> A window frame specification consists of three things:




<ul>
  <li> A frame type - either RANGE or ROWS.
  <li> A starting frame boundary, and
  <li> An ending frame boundary.
</ul>








<p> If the frame type is RANGE, then rows with the same values for all ORDER BY
expressions are considered "peers". Or, if there are no ORDER BY expressions,
all rows are peers. Rows that are peers always have the same window frames.

<p> There are five options for frame boundaries:

<table striped=1>
<tr><th>Frame Boundary <th>Description
<tr><td>UNBOUNDED&nbsp;PRECEDING <td> This may only be used as a starting frame
        boundary. In which case the start of the frame is always the first
        row in the set.
<tr><td>&lt;expr&gt; PRECEDING <td> &lt;expr&gt;, which may not refer to any
        table columns, must evaluate to a non-negative integer value. The start
        or end of the frame is &lt;expr&gt; rows before the current row. "0
        PRECEDING" is the same as "CURRENT ROW". This frame boundary type may
        only be used with ROWS frames.
<tr><td>CURRENT ROW <td> The current row. For RANGE frame types, all peers of
        the current row are also included in the window frame, regardless of
        whether CURRENT ROW is used as the starting or ending frame boundary.
<tr><td>&lt;expr&gt; FOLLOWING <td> &lt;expr&gt;, which may not refer to any
        table columns, must evaluate to a non-negative integer value. The start
        or end of the frame is &lt;expr&gt; rows after the current row. "0
        FOLLOWING" is the same as "CURRENT ROW". This frame boundary type may
        only be used with ROWS frames.
<tr><td>UNBOUNDED&nbsp;FOLLOWING <td> This may only be used as an ending
        frame boundary. In which case the end of the frame is always the last
        row in the set.
</table>

<p> The ending frame boundary must not take a form that appears higher in
the above list than the starting frame boundary.

<p> In the following example, the window frame for each row consists of all







>
|
>
>

|






>
|
|
>
>
>
>



















|
|




>
>
>
|
>
>
>






>
>
>
>
>
>
>









|
<

|
|






|
|



|
<







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
    ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) AS group_concat FROM t1;
</codeblock>

<p> In the example above, the window frame consists of all rows between the
previous row ("1 PRECEDING") and the following row ("1 FOLLOWING"), inclusive,
where rows are sorted according to the ORDER BY clause in the
<yynonterm>window-defn</yynonterm> (in this case "ORDER BY a"). 
For example, the frame for the row with (a=3) consists of rows (2, 'B', 'two'),
(3, 'C', 'three') and (4, 'D', 'one'). The result of group_concat(b, '.') 
for that row is therefore 'B.C.D'.

<p> The default <yynonterm>frame-spec</yynonterm> is:

<codeblock>
    RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
</codeblock>

<p> This means that, after sorting the rows returned by the SELECT according to
the ORDER BY clause in the <yynonterm>window-definition</yynonterm>,
the window frame consists
of all rows between the first row and the last row with the same values as
the current row for all ORDER BY expressions. This implies that rows that
have the same values for all ORDER BY expressions will also have the same
value for the result of the window function (as the window frame is the same).
For example:

<codeblock>
  <i>-- The following SELECT statement returns:</i>
  <i>-- </i>
  <i>--   a | b | c | group_concat</i>
  -----------------------------
  <i>--   1 | A | one   | A.D.G       </i>
  <i>--   2 | B | two   | A.D.G.C.F.B.E</i>
  <i>--   3 | C | three | A.D.G.C.F   </i>
  <i>--   4 | D | one   | A.D.G       </i>
  <i>--   5 | E | two   | A.D.G.C.F.B.E</i>
  <i>--   6 | F | three | A.D.G.C.F   </i>
  <i>--   7 | G | one   | A.D.G       </i>
  <i>-- </i>
  SELECT a, b, c, 
         group_concat(b, '.') OVER (ORDER BY c) AS group_concat 
  FROM t1 ORDER BY a;
</codeblock>

<p> All of SQLite's [Aggregate Functions|aggregate functions] may
be used as aggregate window functions. It is also possible to 
[user-defined window functions|create user-defined aggregate window functions].

<h2>Frame Specifications</h2>

<tcl>
RecursiveBubbleDiagram frame-spec
</tcl>

<p> The <yynonterm>frame-spec</yynonterm> determines which output rows are
read by an aggregate window function.  The
<yynonterm>frame-spec</yynonterm> consists of three parts:

<ul>
  <li> A frame type - either RANGE or ROWS.
  <li> A starting frame boundary, and
  <li> An ending frame boundary.
</ul>

<p>The default 
<yynonterm>frame-spec</yynonterm> is:

<codeblock>
    RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
</codeblock>

<p> If the frame type is RANGE, then rows with the same values for all ORDER BY
expressions are considered "peers". Or, if there are no ORDER BY expressions,
all rows are peers. Rows that are peers always have the same window frames.

<p> There are five options for frame boundaries:

<table striped=1>
<tr><th>Frame Boundary <th>Description
<tr><td>UNBOUNDED&nbsp;PRECEDING <td> The start of the frame is the first

        row in the set.
<tr><td>&lt;expr&gt; PRECEDING <td> &lt;expr&gt; is a constant expression
        that evaluates to a non-negative integer value. The start
        or end of the frame is &lt;expr&gt; rows before the current row. "0
        PRECEDING" is the same as "CURRENT ROW". This frame boundary type may
        only be used with ROWS frames.
<tr><td>CURRENT ROW <td> The current row. For RANGE frame types, all peers of
        the current row are also included in the window frame, regardless of
        whether CURRENT ROW is used as the starting or ending frame boundary.
<tr><td>&lt;expr&gt; FOLLOWING <td> &lt;expr&gt; is a constant expression
        that must evaluate to a non-negative integer value. The start
        or end of the frame is &lt;expr&gt; rows after the current row. "0
        FOLLOWING" is the same as "CURRENT ROW". This frame boundary type may
        only be used with ROWS frames.
<tr><td>UNBOUNDED&nbsp;FOLLOWING <td> The end of the frame is the last

        row in the set.
</table>

<p> The ending frame boundary must not take a form that appears higher in
the above list than the starting frame boundary.

<p> In the following example, the window frame for each row consists of all
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
    ORDER BY c, a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) AS group_concat
  FROM t1 ORDER BY c, a;
</codeblock>

<h2>The PARTITION BY Clause</h2>

<p> A <i>&lt;window-definition&gt;</i> may also include a PARTITION BY clause.
If so, the rows returned by the SELECT statement are divided into groups -
partitions - with the same values for each PARTITION BY expression, and then
window-function processing performed as described above separately for each
partition. This is similar to the way the rows traversed by an aggregate query
are divided into groups before any aggregate processing is performed.

<p> For example:

<codeblock>
  <i>-- The following SELECT statement returns:</i>
  <i>-- </i>
  <i>--   c     | a | b | group_concat</i>







|


|
|
|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    ORDER BY c, a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) AS group_concat
  FROM t1 ORDER BY c, a;
</codeblock>

<h2>The PARTITION BY Clause</h2>

<p> A <yynonterm>window-defn</yynonterm> may include a PARTITION BY clause.
If so, the rows returned by the SELECT statement are divided into groups -
partitions - with the same values for each PARTITION BY expression, and then
window-function processing is performed separately for each
partition. This is similar to the way the rows are grouped by the
GROUP BY clause of an aggregate query.

<p> For example:

<codeblock>
  <i>-- The following SELECT statement returns:</i>
  <i>-- </i>
  <i>--   c     | a | b | group_concat</i>
248
249
250
251
252
253
254




255
256
257
258
259
260
261
    PARTITION BY c ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) AS group_concat
  FROM t1 ORDER BY c, a;
</codeblock>

<h2>The FILTER Clause</h2>





<p>If a FILTER clause is provided, then only rows for which the <i>expr</i> is
true are included in the window frame. The aggregate window still returns a
value for every row, but those for which the FILTER expression evaluates to
other than true are not included in the window frame for any row. For example:

<codeblock>
  <i>-- The following SELECT statement returns:</i>







>
>
>
>







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
    PARTITION BY c ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
  ) AS group_concat
  FROM t1 ORDER BY c, a;
</codeblock>

<h2>The FILTER Clause</h2>

<tcl>
RecursiveBubbleDiagram filter
</tcl>

<p>If a FILTER clause is provided, then only rows for which the <i>expr</i> is
true are included in the window frame. The aggregate window still returns a
value for every row, but those for which the FILTER expression evaluates to
other than true are not included in the window frame for any row. For example:

<codeblock>
  <i>-- The following SELECT statement returns:</i>
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
<p> Built-in window functions honor any PARTITION BY clause in the same way
as aggregate window functions - each selected row is assigned to a partition 
and each partition is processed separately. The ways in which any ORDER BY
clause affects each built-in window function is described below. Some of
the window functions (rank(), dense_rank(), percent_rank() and ntile()) use
the concept of "peer groups" (rows within the same partition that have the
same values for all ORDER BY expressions). In these cases, it does not matter
whether the <i>&lt;frame-specification&gt;</i> specifies ROWS or RANGE - for
the purposes of built-in window function processing, rows with the same values
for all ORDER BY expressions are considered peers regardless of the frame type.

<p> Most built-in window functions ignore the
<i>&lt;frame-specification&gt;</i>, the exceptions being first_value(),
last_value() and nth_value(). It is a syntax error to specify a FILTER 
clause as part of a built-in window function invocation.

<p> SQLite supports the following 11 built-in window functions:

<dl>
  <dt><p><b>row_number()</b>







|




|







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
<p> Built-in window functions honor any PARTITION BY clause in the same way
as aggregate window functions - each selected row is assigned to a partition 
and each partition is processed separately. The ways in which any ORDER BY
clause affects each built-in window function is described below. Some of
the window functions (rank(), dense_rank(), percent_rank() and ntile()) use
the concept of "peer groups" (rows within the same partition that have the
same values for all ORDER BY expressions). In these cases, it does not matter
whether the <yynonterm>frame-spec</yynonterm> specifies ROWS or RANGE - for
the purposes of built-in window function processing, rows with the same values
for all ORDER BY expressions are considered peers regardless of the frame type.

<p> Most built-in window functions ignore the
<yynonterm>frame-spec</yynonterm>, the exceptions being first_value(),
last_value() and nth_value(). It is a syntax error to specify a FILTER 
clause as part of a built-in window function invocation.

<p> SQLite supports the following 11 built-in window functions:

<dl>
  <dt><p><b>row_number()</b>
446
447
448
449
450
451
452

453

454
455
456
457
458
459
460
         ntile(2) OVER win        AS ntile_2,
         ntile(4) OVER win        AS ntile_4
  FROM t2
  WINDOW win AS (ORDER BY a);
</codeblock>

<p> The next example demonstrates lag(), lead(), first_value(), last_value()

and nth_value(). The <i>&lt;frame-specification&gt;</i> is ignored by both lag() and lead(), but respected by first_value(), last_value() and nth_value().


<codeblock>
  <i>-- The following SELECT statement returns:</i>
  <i>-- </i>
  <i>--   b | lead | lag  | first_value | last_value | nth_value_3</i>
  -------------------------------------------------------------
  <i>--   A | C    | NULL | A           | A          | NULL       </i>







>
|
>







470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
         ntile(2) OVER win        AS ntile_2,
         ntile(4) OVER win        AS ntile_4
  FROM t2
  WINDOW win AS (ORDER BY a);
</codeblock>

<p> The next example demonstrates lag(), lead(), first_value(), last_value()
and nth_value(). The <yynonterm>frame-spec</yynonterm> is ignored by 
both lag() and lead(), but respected by first_value(), last_value()
and nth_value().

<codeblock>
  <i>-- The following SELECT statement returns:</i>
  <i>-- </i>
  <i>--   b | lead | lag  | first_value | last_value | nth_value_3</i>
  -------------------------------------------------------------
  <i>--   A | C    | NULL | A           | A          | NULL       </i>
Changes to rawpages/sqlite.css.
222
223
224
225
226
227
228







229
230
231
232
233
234
235
  background: #fff;
  border: 1px solid #000;
  border-radius: 11px;
  padding-left: 4px;
  padding-right: 4px;
  line-height: 125%;
}








/* Container for an image */
.imgcontainer img {
  max-height: 100%;
  max-width: 100%;
}








>
>
>
>
>
>
>







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  background: #fff;
  border: 1px solid #000;
  border-radius: 11px;
  padding-left: 4px;
  padding-right: 4px;
  line-height: 125%;
}
.yynonterm {
  background: #fff;
  border: 1px solid #000;
  padding-left: 2px;
  padding-right: 2px;
  line-height: 125%;
}

/* Container for an image */
.imgcontainer img {
  max-height: 100%;
  max-width: 100%;
}

Changes to search/hdom.tcl.
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  
  # All inline tags.
  variable aInline
  foreach x {
    tt i b big small u
    em strong dfn code samp kbd var cite abbr acronym
    a img object br script map q sub sup span bdo
    input select textarea label button tcl yyterm
  } { set aInline($x) 1 }

  # All self-closing tags (set below)
  variable aSelfClosing

  variable aContentChecker
  set aContentChecker(p)        HtmlInlineContent







|







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  
  # All inline tags.
  variable aInline
  foreach x {
    tt i b big small u
    em strong dfn code samp kbd var cite abbr acronym
    a img object br script map q sub sup span bdo
    input select textarea label button tcl yyterm yynonterm
  } { set aInline($x) 1 }

  # All self-closing tags (set below)
  variable aSelfClosing

  variable aContentChecker
  set aContentChecker(p)        HtmlInlineContent
Changes to wrap.tcl.
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# appropriate <a href=""> markup.
#
# Links to keywords within the same main file are resolved using
# $::llink() if possible.  All other links and links that could
# not be resolved using $::llink() are resolved using $::glink().
# 
proc hd_resolve_2ndpass {text} {
  regsub -all {<yyterm>} $text {<span class='yyterm'>} text
  regsub -all {</yyterm>} $text {</span>} text
  regsub -all {\[(.*?)\]} $text \
      "\175; hd_resolve_one \173\\1\175; hd_puts \173" text
  eval "hd_puts \173$text\175"
}
proc hd_resolve_one {x} {
  if {[string is integer $x] || [string length $x]==1} {
    hd_puts \[$x\]







|
|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# appropriate <a href=""> markup.
#
# Links to keywords within the same main file are resolved using
# $::llink() if possible.  All other links and links that could
# not be resolved using $::llink() are resolved using $::glink().
# 
proc hd_resolve_2ndpass {text} {
  regsub -all {<(yy(non)?term)>} $text {<span class='\1'>} text
  regsub -all {</yy(non)?term>} $text {</span>} text
  regsub -all {\[(.*?)\]} $text \
      "\175; hd_resolve_one \173\\1\175; hd_puts \173" text
  eval "hd_puts \173$text\175"
}
proc hd_resolve_one {x} {
  if {[string is integer $x] || [string length $x]==1} {
    hd_puts \[$x\]