~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to vector/v.digit/html_library.tcl

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Simple HTML display library by Stephen Uhler (stephen.uhler@sun.com)
2
 
# Copyright (c) 1995 by Sun Microsystems
3
 
# Version 0.3 Fri Sep  1 10:47:17 PDT 1995
4
 
#
5
 
# See the file "license.terms" for information on usage and redistribution
6
 
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
7
 
#
8
 
# To use this package,  create a text widget (say, .text)
9
 
# and set a variable full of html, (say $html), and issue:
10
 
#       HMinit_win .text
11
 
#       HMparse_html $html "HMrender .text"
12
 
# You also need to supply the routine:
13
 
#   proc HMlink_callback {win href} { ...}
14
 
#      win:  The name of the text widget
15
 
#      href  The name of the link
16
 
# which will be called anytime the user "clicks" on a link.
17
 
# The supplied version just prints the link to stdout.
18
 
# In addition, if you wish to use embedded images, you will need to write
19
 
#   proc HMset_image {handle src}
20
 
#      handle  an arbitrary handle (not really)
21
 
#      src     The name of the image
22
 
# Which calls
23
 
#       HMgot_image $handle $image
24
 
# with the TK image.
25
 
#
26
 
# To return a "used" text widget to its initialized state, call:
27
 
#   HMreset_win .text
28
 
# See "sample.tcl" for sample usage
29
 
##################################################################
30
 
 
31
 
# Include the select dialog code because it defines scroll bindings
32
 
source $env(GISBASE)/etc/gtcltk/select.tcl
33
 
 
34
 
 
35
 
############################################
36
 
# mapping of html tags to text tag properties
37
 
# properties beginning with "T" map directly to text tags
38
 
 
39
 
# These are Defined in HTML 2.0
40
 
 
41
 
array set HMtag_map {
42
 
        b      {weight bold}
43
 
        blockquote      {style i indent 1 Trindent rindent}
44
 
        bq              {style i indent 1 Trindent rindent}
45
 
        cite   {style i}
46
 
        code   {family courier}
47
 
        dfn    {style i}        
48
 
        dir    {indent 1}
49
 
        dl     {indent 1}
50
 
        em     {style i}
51
 
        h1     {size 24 weight bold}
52
 
        h2     {size 22}                
53
 
        h3     {size 20}        
54
 
        h4     {size 18}
55
 
        h5     {size 16}
56
 
        h6     {style i}
57
 
        i      {style i}
58
 
        kbd    {family courier weight bold}
59
 
        menu     {indent 1}
60
 
        ol     {indent 1}
61
 
        pre    {fill 0 family courier Tnowrap nowrap}
62
 
        samp   {family courier}         
63
 
        strong {weight bold}            
64
 
        tt     {family courier}
65
 
        u        {Tunderline underline}
66
 
        ul     {indent 1}
67
 
        var    {style i}        
68
 
}
69
 
 
70
 
# These are in common(?) use, but not defined in html2.0
71
 
 
72
 
array set HMtag_map {
73
 
        center {Tcenter center}
74
 
        strike {Tstrike strike}
75
 
        u          {Tunderline underline}
76
 
}
77
 
 
78
 
# initial values
79
 
 
80
 
set HMtag_map(hmstart) {
81
 
        family times   weight medium   style r   size 14
82
 
        Tcenter ""   Tlink ""   Tnowrap ""   Tunderline ""   list list
83
 
        fill 1   indent "" counter 0 adjust 0
84
 
}
85
 
 
86
 
# html tags that insert white space
87
 
 
88
 
array set HMinsert_map {
89
 
        blockquote "\n\n" /blockquote "\n"
90
 
        br      "\n"
91
 
        dd      "\n" /dd        "\n"
92
 
        dl      "\n" /dl        "\n"
93
 
        dt      "\n"
94
 
        form "\n"       /form "\n"
95
 
        h1      "\n\n"  /h1     "\n"
96
 
        h2      "\n\n"  /h2     "\n"
97
 
        h3      "\n\n"  /h3     "\n"
98
 
        h4      "\n"    /h4     "\n"
99
 
        h5      "\n"    /h5     "\n"
100
 
        h6      "\n"    /h6     "\n"
101
 
        li   "\n"
102
 
        /dir "\n"
103
 
        /ul "\n"
104
 
        /ol "\n"
105
 
        /menu "\n"
106
 
        p       "\n\n"
107
 
        pre "\n"        /pre "\n"
108
 
}
109
 
 
110
 
# tags that are list elements, that support "compact" rendering
111
 
 
112
 
array set HMlist_elements {
113
 
        ol 1   ul 1   menu 1   dl 1   dir 1
114
 
}
115
 
############################################
116
 
# initialize the window and stack state
117
 
 
118
 
proc HMinit_win {win} {
119
 
        upvar #0 HM$win var
120
 
        
121
 
        HMinit_state $win
122
 
        $win tag configure underline -underline 1
123
 
        $win tag configure center -justify center
124
 
        $win tag configure nowrap -wrap none
125
 
        $win tag configure rindent -rmargin $var(S_tab)c
126
 
        $win tag configure strike -overstrike 1
127
 
        $win tag configure mark -foreground red         ;# list markers
128
 
        $win tag configure list -spacing1 3p -spacing3 3p               ;# regular lists
129
 
        $win tag configure compact -spacing1 0p         ;# compact lists
130
 
        $win tag configure link -borderwidth 2 -foreground blue ;# hypertext links
131
 
        HMset_indent $win $var(S_tab)
132
 
        $win configure -wrap word
133
 
 
134
 
        # configure the text insertion point
135
 
        $win mark set $var(S_insert) 1.0
136
 
 
137
 
        # for horizontal rules
138
 
        $win tag configure thin -font [HMx_font times 2 medium r]
139
 
        $win tag configure hr -relief sunken -borderwidth 2 -wrap none \
140
 
                -tabs [winfo width $win]
141
 
        bind $win <Configure> {
142
 
                %W tag configure hr -tabs %w
143
 
                %W tag configure last -spacing3 %h
144
 
        }
145
 
 
146
 
        # generic link enter callback
147
 
 
148
 
        $win tag bind link <1> "HMlink_hit $win %x %y"
149
 
}
150
 
 
151
 
# set the indent spacing (in cm) for lists
152
 
# TK uses a "weird" tabbing model that causes \t to insert a single
153
 
# space if the current line position is past the tab setting
154
 
 
155
 
proc HMset_indent {win cm} {
156
 
        set tabs [expr $cm / 2.0]
157
 
        $win configure -tabs ${tabs}c
158
 
        foreach i {1 2 3 4 5 6 7 8 9} {
159
 
                set tab [expr $i * $cm]
160
 
                $win tag configure indent$i -lmargin1 ${tab}c -lmargin2 ${tab}c \
161
 
                        -tabs "[expr $tab + $tabs]c [expr $tab + 2*$tabs]c"
162
 
        }
163
 
}
164
 
 
165
 
# reset the state of window - get ready for the next page
166
 
# remove all but the font tags, and remove all form state
167
 
 
168
 
proc HMreset_win {win} {
169
 
        upvar #0 HM$win var
170
 
        regsub -all { +[^L ][^ ]*} " [$win tag names] " {} tags
171
 
        catch "$win tag delete $tags"
172
 
        eval $win mark unset [$win mark names]
173
 
        $win delete 0.0 end
174
 
        $win tag configure hr -tabs [winfo width $win]
175
 
 
176
 
        # configure the text insertion point
177
 
        $win mark set $var(S_insert) 1.0
178
 
 
179
 
        # remove form state.  If any check/radio buttons still exists, 
180
 
        # their variables will be magically re-created, and never get
181
 
        # cleaned up.
182
 
        catch unset [info globals HM$win.form*]
183
 
 
184
 
        HMinit_state $win
185
 
        return HM$win
186
 
}
187
 
 
188
 
# initialize the window's state array
189
 
# Parameters beginning with S_ are NOT reset
190
 
#  adjust_size:         global font size adjuster
191
 
#  unknown:             character to use for unknown entities
192
 
#  tab:                 tab stop (in cm)
193
 
#  stop:                enabled to stop processing
194
 
#  update:              how many tags between update calls
195
 
#  tags:                number of tags processed so far
196
 
#  symbols:             Symbols to use on un-ordered lists
197
 
 
198
 
proc HMinit_state {win} {
199
 
        upvar #0 HM$win var
200
 
        array set tmp [array get var S_*]
201
 
        catch {unset var}
202
 
        array set var {
203
 
                stop 0
204
 
                tags 0
205
 
                fill 0
206
 
                list list
207
 
                S_adjust_size 0
208
 
                S_tab 1.0
209
 
                S_unknown \xb7
210
 
                S_update 10
211
 
                S_symbols O*=+-o\xd7\xb0>:\xb7
212
 
                S_insert Insert
213
 
        }
214
 
        array set var [array get tmp]
215
 
}
216
 
 
217
 
# alter the parameters of the text state
218
 
# this allows an application to over-ride the default settings
219
 
# it is called as: HMset_state -param value -param value ...
220
 
 
221
 
array set HMparam_map {
222
 
        -update S_update
223
 
        -tab S_tab
224
 
        -unknown S_unknown
225
 
        -stop S_stop
226
 
        -size S_adjust_size
227
 
        -symbols S_symbols
228
 
    -insert S_insert
229
 
}
230
 
 
231
 
proc HMset_state {win args} {
232
 
        upvar #0 HM$win var
233
 
        global HMparam_map
234
 
        set bad 0
235
 
        if {[catch {array set params $args}]} {return 0}
236
 
        foreach i [array names params] {
237
 
                incr bad [catch {set var($HMparam_map($i)) $params($i)}]
238
 
        }
239
 
        return [expr $bad == 0]
240
 
}
241
 
 
242
 
############################################
243
 
# manage the display of html
244
 
 
245
 
# HMrender gets called for every html tag
246
 
#   win:   The name of the text widget to render into
247
 
#   tag:   The html tag (in arbitrary case)
248
 
#   not:   a "/" or the empty string
249
 
#   param: The un-interpreted parameter list
250
 
#   text:  The plain text until the next html tag
251
 
 
252
 
proc HMrender {win tag not param text} {
253
 
        upvar #0 HM$win var
254
 
        if {$var(stop)} return
255
 
        global HMtag_map HMinsert_map HMlist_elements
256
 
        set tag [string tolower $tag]
257
 
        set text [HMmap_esc $text]
258
 
 
259
 
        # manage compact rendering of lists
260
 
        if {[info exists HMlist_elements($tag)]} {
261
 
                set list "list [expr {[HMextract_param $param compact] ? "compact" : "list"}]"
262
 
        } else {
263
 
                set list ""
264
 
        }
265
 
 
266
 
        # Allow text to be diverted to a different window (for tables)
267
 
        # this is not currently used
268
 
        if {[info exists var(divert)]} {
269
 
                set win $var(divert)
270
 
                upvar #0 HM$win var
271
 
        }
272
 
 
273
 
        # adjust (push or pop) tag state
274
 
        catch {HMstack $win $not "$HMtag_map($tag) $list"}
275
 
 
276
 
        # insert white space (with current font)
277
 
        # adding white space can get a bit tricky.  This isn't quite right
278
 
        set bad [catch {$win insert $var(S_insert) $HMinsert_map($not$tag) "space $var(font)"}]
279
 
        if {!$bad && [lindex $var(fill) end]} {
280
 
                set text [string trimleft $text]
281
 
        }
282
 
 
283
 
        # to fill or not to fill
284
 
        if {[lindex $var(fill) end]} {
285
 
                set text [HMzap_white $text]
286
 
        }
287
 
 
288
 
        # generic mark hook
289
 
        catch {HMmark $not$tag $win $param text} err
290
 
 
291
 
        # do any special tag processing
292
 
        catch {HMtag_$not$tag $win $param text} msg
293
 
 
294
 
 
295
 
        # add the text with proper tags
296
 
 
297
 
        set tags [HMcurrent_tags $win]
298
 
        $win insert $var(S_insert) $text $tags
299
 
 
300
 
        # We need to do an update every so often to insure interactive response.
301
 
        # This can cause us to re-enter the event loop, and cause recursive
302
 
        # invocations of HMrender, so we need to be careful.
303
 
        if {!([incr var(tags)] % $var(S_update))} {
304
 
                update
305
 
        }
306
 
}
307
 
 
308
 
# html tags requiring special processing
309
 
# Procs of the form HMtag_<tag> or HMtag_</tag> get called just before
310
 
# the text for this tag is displayed.  These procs are called inside a 
311
 
# "catch" so it is OK to fail.
312
 
#   win:   The name of the text widget to render into
313
 
#   param: The un-interpreted parameter list
314
 
#   text:  A pass-by-reference name of the plain text until the next html tag
315
 
#          Tag commands may change this to affect what text will be inserted
316
 
#          next.
317
 
 
318
 
# A pair of pseudo tags are added automatically as the 1st and last html
319
 
# tags in the document.  The default is <HMstart> and </HMstart>.
320
 
# Append enough blank space at the end of the text widget while
321
 
# rendering so HMgoto can place the target near the top of the page,
322
 
# then remove the extra space when done rendering.
323
 
 
324
 
proc HMtag_hmstart {win param text} {
325
 
        upvar #0 HM$win var
326
 
        $win mark gravity $var(S_insert) left
327
 
        $win insert end "\n " last
328
 
        $win mark gravity $var(S_insert) right
329
 
}
330
 
 
331
 
proc HMtag_/hmstart {win param text} {
332
 
        $win delete last.first end
333
 
}
334
 
 
335
 
# put the document title in the window banner, and remove the title text
336
 
# from the document
337
 
 
338
 
proc HMtag_title {win param text} {
339
 
        upvar $text data
340
 
        wm title [winfo toplevel $win] $data
341
 
        set data ""
342
 
}
343
 
 
344
 
proc HMtag_hr {win param text} {
345
 
        upvar #0 HM$win var
346
 
        $win insert $var(S_insert) "\n" space "\n" thin "\t" "thin hr" "\n" thin
347
 
}
348
 
 
349
 
# list element tags
350
 
 
351
 
proc HMtag_ol {win param text} {
352
 
        upvar #0 HM$win var
353
 
        set var(count$var(level)) 0
354
 
}
355
 
 
356
 
proc HMtag_ul {win param text} {
357
 
        upvar #0 HM$win var
358
 
        catch {unset var(count$var(level))}
359
 
}
360
 
 
361
 
proc HMtag_menu {win param text} {
362
 
        upvar #0 HM$win var
363
 
        set var(menu) ->
364
 
        set var(compact) 1
365
 
}
366
 
 
367
 
proc HMtag_/menu {win param text} {
368
 
        upvar #0 HM$win var
369
 
        catch {unset var(menu)}
370
 
        catch {unset var(compact)}
371
 
}
372
 
        
373
 
proc HMtag_dt {win param text} {
374
 
        upvar #0 HM$win var
375
 
        upvar $text data
376
 
        set level $var(level)
377
 
        incr level -1
378
 
        $win insert $var(S_insert) "$data" \
379
 
                "hi [lindex $var(list) end] indent$level $var(font)"
380
 
        set data {}
381
 
}
382
 
 
383
 
proc HMtag_li {win param text} {
384
 
        upvar #0 HM$win var
385
 
        set level $var(level)
386
 
        incr level -1
387
 
        set x [string index $var(S_symbols)+-+-+-+-" $level]
388
 
        catch {set x [incr var(count$level)]}
389
 
        catch {set x $var(menu)}
390
 
        $win insert $var(S_insert) \t$x\t "mark [lindex $var(list) end] indent$level $var(font)"
391
 
}
392
 
 
393
 
# Manage hypertext "anchor" links.  A link can be either a source (href)
394
 
# a destination (name) or both.  If its a source, register it via a callback,
395
 
# and set its default behavior.  If its a destination, check to see if we need
396
 
# to go there now, as a result of a previous HMgoto request.  If so, schedule
397
 
# it to happen with the closing </a> tag, so we can highlight the text up to
398
 
# the </a>.
399
 
 
400
 
proc HMtag_a {win param text} {
401
 
        upvar #0 HM$win var
402
 
 
403
 
        # a source
404
 
 
405
 
        if {[HMextract_param $param href]} {
406
 
                set var(Tref) [list L:$href]
407
 
                HMstack $win "" "Tlink link"
408
 
                HMlink_setup $win $href
409
 
        }
410
 
 
411
 
        # a destination
412
 
 
413
 
        if {[HMextract_param $param name]} {
414
 
                set var(Tname) [list N:$name]
415
 
                HMstack $win "" "Tanchor anchor"
416
 
                $win mark set N:$name "$var(S_insert) - 1 chars"
417
 
                $win mark gravity N:$name left
418
 
                if {[info exists var(goto)] && $var(goto) == $name} {
419
 
                        unset var(goto)
420
 
                        set var(going) $name
421
 
                }
422
 
        }
423
 
}
424
 
 
425
 
# The application should call here with the fragment name
426
 
# to cause the display to go to this spot.
427
 
# If the target exists, go there (and do the callback),
428
 
# otherwise schedule the goto to happen when we see the reference.
429
 
 
430
 
proc HMgoto {win where {callback HMwent_to}} {
431
 
        upvar #0 HM$win var
432
 
        if {[regexp N:$where [$win mark names]]} {
433
 
                $win see N:$where
434
 
                update
435
 
                eval $callback $win [list $where]
436
 
                return 1
437
 
        } else {
438
 
                set var(goto) $where
439
 
                return 0
440
 
        }
441
 
}
442
 
 
443
 
# We actually got to the spot, so highlight it!
444
 
# This should/could be replaced by the application
445
 
# We'll flash it orange a couple of times.
446
 
 
447
 
proc HMwent_to {win where {count 0} {color orange}} {
448
 
        upvar #0 HM$win var
449
 
        if {$count > 5} return
450
 
        catch {$win tag configure N:$where -foreground $color}
451
 
        update
452
 
        after 200 [list HMwent_to $win $where [incr count] \
453
 
                                [expr {$color=="orange" ? "" : "orange"}]]
454
 
}
455
 
 
456
 
proc HMtag_/a {win param text} {
457
 
        upvar #0 HM$win var
458
 
        if {[info exists var(Tref)]} {
459
 
                unset var(Tref)
460
 
                HMstack $win / "Tlink link"
461
 
        }
462
 
 
463
 
        # goto this link, then invoke the call-back.
464
 
 
465
 
        if {[info exists var(going)]} {
466
 
                $win yview N:$var(going)
467
 
                update
468
 
                HMwent_to $win $var(going)
469
 
                unset var(going)
470
 
        }
471
 
 
472
 
        if {[info exists var(Tname)]} {
473
 
                unset var(Tname)
474
 
                HMstack $win / "Tanchor anchor"
475
 
        }
476
 
}
477
 
 
478
 
#           Inline Images
479
 
# This interface is subject to change
480
 
# Most of the work is getting around a limitation of TK that prevents
481
 
# setting the size of a label to a widthxheight in pixels
482
 
#
483
 
# Images have the following parameters:
484
 
#    align:  top,middle,bottom
485
 
#    alt:    alternate text
486
 
#    ismap:  A clickable image map
487
 
#    src:    The URL link
488
 
# Netscape supports (and so do we)
489
 
#    width:  A width hint (in pixels)
490
 
#    height:  A height hint (in pixels)
491
 
#    border: The size of the window border
492
 
 
493
 
proc HMtag_img {win param text} {
494
 
        upvar #0 HM$win var
495
 
 
496
 
        # get alignment
497
 
        array set align_map {top top    middle center    bottom bottom}
498
 
        set align bottom                ;# The spec isn't clear what the default should be
499
 
        HMextract_param $param align
500
 
        catch {set align $align_map([string tolower $align])}
501
 
 
502
 
        # get alternate text
503
 
        set alt "<image>"
504
 
        HMextract_param $param alt
505
 
        set alt [HMmap_esc $alt]
506
 
 
507
 
        # get the border width
508
 
        set border 1
509
 
        HMextract_param $param border
510
 
 
511
 
        # see if we have an image size hint
512
 
        # If so, make a frame the "hint" size to put the label in
513
 
        # otherwise just make the label
514
 
        set item $win.$var(tags)
515
 
        # catch {destroy $item}
516
 
        if {[HMextract_param $param width] && [HMextract_param $param height]} {
517
 
                frame $item -width $width -height $height
518
 
                pack propagate $item 0
519
 
                set label $item.label
520
 
                label $label
521
 
                pack $label -expand 1 -fill both
522
 
        } else {
523
 
                set label $item
524
 
                label $label 
525
 
        }
526
 
 
527
 
        $label configure -relief ridge -fg orange -text $alt
528
 
        catch {$label configure -bd $border}
529
 
        $win window create $var(S_insert) -align $align -window $item -pady 2 -padx 2
530
 
 
531
 
        # add in all the current tags (this is overkill)
532
 
        set tags [HMcurrent_tags $win]
533
 
        foreach tag $tags {
534
 
                $win tag add $tag $item
535
 
        }
536
 
 
537
 
        # set imagemap callbacks
538
 
        if {[HMextract_param $param ismap]} {
539
 
                # regsub -all {[^L]*L:([^ ]*).*}  $tags {\1} link
540
 
                set link [lindex $tags [lsearch -glob $tags L:*]]
541
 
                regsub L: $link {} link
542
 
                global HMevents
543
 
                regsub -all {%} $link {%%} link2
544
 
                foreach i [array names HMevents] {
545
 
                        bind $label <$i> "catch \{%W configure $HMevents($i)\}"
546
 
                }
547
 
                bind $label <1> "+HMlink_callback $win $link2?%x,%y"
548
 
        } 
549
 
 
550
 
        # now callback to the application
551
 
        set src ""
552
 
        HMextract_param $param src
553
 
        HMset_image $win $label $src
554
 
        return $label   ;# used by the forms package for input_image types
555
 
}
556
 
 
557
 
# The app needs to supply one of these
558
 
proc HMset_image {win handle src} {
559
 
        HMgot_image $handle "can't get\n$src"
560
 
}
561
 
 
562
 
# When the image is available, the application should call back here.
563
 
# If we have the image, put it in the label, otherwise display the error
564
 
# message.  If we don't get a callback, the "alt" text remains.
565
 
# if we have a clickable image, arrange for a callback
566
 
 
567
 
proc HMgot_image {win image_error} {
568
 
        # if we're in a frame turn on geometry propogation
569
 
        if {[winfo name $win] == "label"} {
570
 
                pack propagate [winfo parent $win] 1
571
 
        }
572
 
        if {[catch {$win configure -image $image_error}]} {
573
 
                $win configure -image {}
574
 
                $win configure -text $image_error
575
 
        }
576
 
}
577
 
 
578
 
# Sample hypertext link callback routine - should be replaced by app
579
 
# This proc is called once for each <A> tag.
580
 
# Applications can overwrite this procedure, as required, or
581
 
# replace the HMevents array
582
 
#   win:   The name of the text widget to render into
583
 
#   href:  The HREF link for this <a> tag.
584
 
 
585
 
array set HMevents {
586
 
        Enter   {-borderwidth 2 -relief raised }
587
 
        Leave   {-borderwidth 2 -relief flat }
588
 
        1               {-borderwidth 2 -relief sunken}
589
 
        ButtonRelease-1 {-borderwidth 2 -relief raised}
590
 
}
591
 
 
592
 
# We need to escape any %'s in the href tag name so the bind command
593
 
# doesn't try to substitute them.
594
 
 
595
 
proc HMlink_setup {win href} {
596
 
        global HMevents
597
 
        regsub -all {%} $href {%%} href2
598
 
        foreach i [array names HMevents] {
599
 
                eval {$win tag bind  L:$href <$i>} \
600
 
                        \{$win tag configure \{L:$href2\} $HMevents($i)\}
601
 
        }
602
 
}
603
 
 
604
 
# generic link-hit callback
605
 
# This gets called upon button hits on hypertext links
606
 
# Applications are expected to supply ther own HMlink_callback routine
607
 
#   win:   The name of the text widget to render into
608
 
#   x,y:   The cursor position at the "click"
609
 
 
610
 
proc HMlink_hit {win x y} {
611
 
        set tags [$win tag names @$x,$y]
612
 
        set link [lindex $tags [lsearch -glob $tags L:*]]
613
 
        # regsub -all {[^L]*L:([^ ]*).*}  $tags {\1} link
614
 
        regsub L: $link {} link
615
 
        HMlink_callback $win $link
616
 
}
617
 
 
618
 
# replace this!
619
 
#   win:   The name of the text widget to render into
620
 
#   href:  The HREF link for this <a> tag.
621
 
 
622
 
proc HMlink_callback {win href} {
623
 
        puts "Got hit on $win, link $href"
624
 
}
625
 
 
626
 
# extract a value from parameter list (this needs a re-do)
627
 
# returns "1" if the keyword is found, "0" otherwise
628
 
#   param:  A parameter list.  It should alredy have been processed to
629
 
#           remove any entity references
630
 
#   key:    The parameter name
631
 
#   val:    The variable to put the value into (use key as default)
632
 
 
633
 
proc HMextract_param {param key {val ""}} {
634
 
 
635
 
        if {$val == ""} {
636
 
                upvar $key result
637
 
        } else {
638
 
                upvar $val result
639
 
        }
640
 
    set ws "    \n\r"
641
 
 
642
 
    # look for name=value combinations.  Either (') or (") are valid delimeters
643
 
    if {
644
 
      [regsub -nocase [format {.*%s[%s]*=[%s]*"([^"]*).*} $key $ws $ws] $param {\1} value] ||
645
 
      [regsub -nocase [format {.*%s[%s]*=[%s]*'([^']*).*} $key $ws $ws] $param {\1} value] ||
646
 
      [regsub -nocase [format {.*%s[%s]*=[%s]*([^%s]+).*} $key $ws $ws $ws] $param {\1} value] } {
647
 
        set result $value
648
 
        return 1
649
 
    }
650
 
 
651
 
        # now look for valueless names
652
 
        # I should strip out name=value pairs, so we don't end up with "name"
653
 
        # inside the "value" part of some other key word - some day
654
 
        
655
 
        set bad \[^a-zA-Z\]+
656
 
        if {[regexp -nocase  "$bad$key$bad" -$param-]} {
657
 
                return 1
658
 
        } else {
659
 
                return 0
660
 
        }
661
 
}
662
 
 
663
 
# These next two routines manage the display state of the page.
664
 
 
665
 
# Push or pop tags to/from stack.
666
 
# Each orthogonal text property has its own stack, stored as a list.
667
 
# The current (most recent) tag is the last item on the list.
668
 
# Push is {} for pushing and {/} for popping
669
 
 
670
 
proc HMstack {win push list} {
671
 
        upvar #0 HM$win var
672
 
        array set tags $list
673
 
        if {$push == ""} {
674
 
                foreach tag [array names tags] {
675
 
                        lappend var($tag) $tags($tag)
676
 
                }
677
 
        } else {
678
 
                foreach tag [array names tags] {
679
 
                        # set cnt [regsub { *[^ ]+$} $var($tag) {} var($tag)]
680
 
                        set var($tag) [lreplace $var($tag) end end]
681
 
                }
682
 
        }
683
 
}
684
 
 
685
 
# extract set of current text tags
686
 
# tags starting with T map directly to text tags, all others are
687
 
# handled specially.  There is an application callback, HMset_font
688
 
# to allow the application to do font error handling
689
 
 
690
 
proc HMcurrent_tags {win} {
691
 
        upvar #0 HM$win var
692
 
        set font font
693
 
        foreach i {family size weight style} {
694
 
                set $i [lindex $var($i) end]
695
 
                append font :[set $i]
696
 
        }
697
 
        set xfont [HMx_font $family $size $weight $style $var(S_adjust_size)]
698
 
        HMset_font $win $font $xfont
699
 
        set indent [llength $var(indent)]
700
 
        incr indent -1
701
 
        lappend tags $font indent$indent
702
 
        foreach tag [array names var T*] {
703
 
                lappend tags [lindex $var($tag) end]    ;# test
704
 
        }
705
 
        set var(font) $font
706
 
        set var(xfont) [$win tag cget $font -font]
707
 
        set var(level) $indent
708
 
        return $tags
709
 
}
710
 
 
711
 
# allow the application to do do better font management
712
 
# by overriding this procedure
713
 
 
714
 
proc HMset_font {win tag font} {
715
 
        catch {$win tag configure $tag -font $font} msg
716
 
}
717
 
 
718
 
# generate an X font name
719
 
proc HMx_font {family size weight style {adjust_size 0}} {
720
 
        catch {incr size $adjust_size}
721
 
        return "-*-$family-$weight-$style-normal-*-*-${size}0-*-*-*-*-*-*"
722
 
}
723
 
 
724
 
# Optimize HMrender (hee hee)
725
 
# This is experimental
726
 
 
727
 
proc HMoptimize {} {
728
 
        regsub -all "\n\[       \]*#\[^\n\]*" [info body HMrender] {} body
729
 
        regsub -all ";\[        \]*#\[^\n]*" $body {} body
730
 
        regsub -all "\n\n+" $body \n body
731
 
        proc HMrender {win tag not param text} $body
732
 
}
733
 
############################################
734
 
# Turn HTML into TCL commands
735
 
#   html    A string containing an html document
736
 
#   cmd         A command to run for each html tag found
737
 
#   start       The name of the dummy html start/stop tags
738
 
 
739
 
proc HMparse_html {html {cmd HMtest_parse} {start hmstart}} {
740
 
        regsub -all \{ $html {\&ob;} html
741
 
        regsub -all \} $html {\&cb;} html
742
 
        set w " \t\r\n" ;# white space
743
 
        proc HMcl x {return "\[$x\]"}
744
 
        set exp <(/?)([HMcl ^$w>]+)[HMcl $w]*([HMcl ^>]*)>
745
 
        set sub "\}\n$cmd {\\2} {\\1} {\\3} \{"
746
 
        regsub -all $exp $html $sub html
747
 
        eval "$cmd {$start} {} {} \{ $html \}"
748
 
        eval "$cmd {$start} / {} {}"
749
 
}
750
 
 
751
 
proc HMtest_parse {command tag slash text_after_tag} {
752
 
        puts "==> $command $tag $slash $text_after_tag"
753
 
}
754
 
 
755
 
# Convert multiple white space into a single space
756
 
 
757
 
proc HMzap_white {data} {
758
 
        regsub -all "\[ \t\r\n\]+" $data " " data
759
 
        return $data
760
 
}
761
 
 
762
 
# find HTML escape characters of the form &xxx;
763
 
 
764
 
proc HMmap_esc {text} {
765
 
        if {![regexp & $text]} {return $text}
766
 
        regsub -all {([][$\\])} $text {\\\1} new
767
 
        regsub -all {&#([0-9][0-9]?[0-9]?);?} \
768
 
                $new {[format %c [scan \1 %d tmp;set tmp]]} new
769
 
        regsub -all {&([a-zA-Z]+);?} $new {[HMdo_map \1]} new
770
 
        return [subst $new]
771
 
}
772
 
 
773
 
# convert an HTML escape sequence into character
774
 
 
775
 
proc HMdo_map {text {unknown ?}} {
776
 
        global HMesc_map
777
 
        set result $unknown
778
 
        catch {set result $HMesc_map($text)}
779
 
        return $result
780
 
}
781
 
 
782
 
# table of escape characters (ISO latin-1 esc's are in a different table)
783
 
 
784
 
array set HMesc_map {
785
 
   lt <   gt >   amp &   quot \"   copy \xa9
786
 
   reg \xae   ob \x7b   cb \x7d   nbsp \xa0
787
 
}
788
 
#############################################################
789
 
# ISO Latin-1 escape codes
790
 
 
791
 
array set HMesc_map {
792
 
        nbsp \xa0 iexcl \xa1 cent \xa2 pound \xa3 curren \xa4
793
 
        yen \xa5 brvbar \xa6 sect \xa7 uml \xa8 copy \xa9
794
 
        ordf \xaa laquo \xab not \xac shy \xad reg \xae
795
 
        hibar \xaf deg \xb0 plusmn \xb1 sup2 \xb2 sup3 \xb3
796
 
        acute \xb4 micro \xb5 para \xb6 middot \xb7 cedil \xb8
797
 
        sup1 \xb9 ordm \xba raquo \xbb frac14 \xbc frac12 \xbd
798
 
        frac34 \xbe iquest \xbf Agrave \xc0 Aacute \xc1 Acirc \xc2
799
 
        Atilde \xc3 Auml \xc4 Aring \xc5 AElig \xc6 Ccedil \xc7
800
 
        Egrave \xc8 Eacute \xc9 Ecirc \xca Euml \xcb Igrave \xcc
801
 
        Iacute \xcd Icirc \xce Iuml \xcf ETH \xd0 Ntilde \xd1
802
 
        Ograve \xd2 Oacute \xd3 Ocirc \xd4 Otilde \xd5 Ouml \xd6
803
 
        times \xd7 Oslash \xd8 Ugrave \xd9 Uacute \xda Ucirc \xdb
804
 
        Uuml \xdc Yacute \xdd THORN \xde szlig \xdf agrave \xe0
805
 
        aacute \xe1 acirc \xe2 atilde \xe3 auml \xe4 aring \xe5
806
 
        aelig \xe6 ccedil \xe7 egrave \xe8 eacute \xe9 ecirc \xea
807
 
        euml \xeb igrave \xec iacute \xed icirc \xee iuml \xef
808
 
        eth \xf0 ntilde \xf1 ograve \xf2 oacute \xf3 ocirc \xf4
809
 
        otilde \xf5 ouml \xf6 divide \xf7 oslash \xf8 ugrave \xf9
810
 
        uacute \xfa ucirc \xfb uuml \xfc yacute \xfd thorn \xfe
811
 
        yuml \xff
812
 
}
813
 
 
814
 
##########################################################
815
 
# html forms management commands
816
 
 
817
 
# As each form element is located, it is created and rendered.  Additional
818
 
# state is stored in a form specific global variable to be processed at
819
 
# the end of the form, including the "reset" and "submit" options.
820
 
# Remember, there can be multiple forms existing on multiple pages.  When
821
 
# HTML tables are added, a single form could be spread out over multiple
822
 
# text widgets, which makes it impractical to hang the form state off the
823
 
# HM$win structure.  We don't need to check for the existance of required
824
 
# parameters, we just "fail" and get caught in HMrender
825
 
 
826
 
# This causes line breaks to be preserved in the inital values
827
 
# of text areas
828
 
array set HMtag_map {
829
 
        textarea    {fill 0}
830
 
}
831
 
 
832
 
##########################################################
833
 
# html isindex tag.  Although not strictly forms, they're close enough
834
 
# to be in this file
835
 
 
836
 
# is-index forms
837
 
# make a frame with a label, entry, and submit button
838
 
 
839
 
proc HMtag_isindex {win param text} {
840
 
        upvar #0 HM$win var
841
 
 
842
 
        set item $win.$var(tags)
843
 
        if {[winfo exists $item]} {
844
 
                destroy $item
845
 
        }
846
 
        frame $item -relief ridge -bd 3
847
 
        set prompt "Enter search keywords here"
848
 
        HMextract_param $param prompt
849
 
        label $item.label -text [HMmap_esc $prompt] -font $var(xfont)
850
 
        entry $item.entry
851
 
        bind $item.entry <Return> "$item.submit invoke"
852
 
        button $item.submit -text search -font $var(xfont) -command \
853
 
                [format {HMsubmit_index %s {%s} [HMmap_reply [%s get]]} \
854
 
                $win $param $item.entry]
855
 
        pack $item.label -side top
856
 
        pack $item.entry $item.submit -side left
857
 
 
858
 
        # insert window into text widget
859
 
 
860
 
        $win insert $var(S_insert) \n isindex
861
 
        HMwin_install $win $item
862
 
        $win insert $var(S_insert) \n isindex
863
 
        bind $item <Visibility> {focus %W.entry}
864
 
}
865
 
 
866
 
# This is called when the isindex form is submitted.
867
 
# The default version calls HMlink_callback.  Isindex tags should either
868
 
# be deprecated, or fully supported (e.g. they need an href parameter)
869
 
 
870
 
proc HMsubmit_index {win param text} {
871
 
        HMlink_callback $win ?$text
872
 
}
873
 
 
874
 
# initialize form state.  All of the state for this form is kept
875
 
# in a global array whose name is stored in the form_id field of
876
 
# the main window array.
877
 
# Parameters: ACTION, METHOD, ENCTYPE
878
 
 
879
 
proc HMtag_form {win param text} {
880
 
        upvar #0 HM$win var
881
 
 
882
 
        # create a global array for the form
883
 
        set id HM$win.form$var(tags)
884
 
        upvar #0 $id form
885
 
 
886
 
        # missing /form tag, simulate it
887
 
        if {[info exists var(form_id)]} {
888
 
                puts "Missing end-form tag !!!! $var(form_id)"
889
 
                HMtag_/form $win {} {}
890
 
        }
891
 
        catch {unset form}
892
 
        set var(form_id) $id
893
 
 
894
 
        set form(param) $param          ;# form initial parameter list
895
 
        set form(reset) ""                      ;# command to reset the form
896
 
        set form(reset_button) ""       ;# list of all reset buttons
897
 
        set form(submit) ""                     ;# command to submit the form
898
 
        set form(submit_button) ""      ;# list of all submit buttons
899
 
}
900
 
 
901
 
# Where we're done try to get all of the state into the widgets so
902
 
# we can free up the form structure here.  Unfortunately, we can't!
903
 
 
904
 
proc HMtag_/form {win param text} {
905
 
        upvar #0 HM$win var
906
 
        upvar #0 $var(form_id) form
907
 
 
908
 
        # make submit button entries for all radio buttons
909
 
        foreach name [array names form radio_*] {
910
 
                regsub radio_ $name {} name
911
 
                lappend form(submit) [list $name \$form(radio_$name)]
912
 
        }
913
 
 
914
 
        # no submit button - add one
915
 
        if {$form(submit_button) == ""} {
916
 
                HMinput_submit $win {}
917
 
                                
918
 
        }
919
 
        
920
 
        # process the "submit" command(s)
921
 
        # each submit button could have its own name,value pair
922
 
 
923
 
        foreach item $form(submit_button) {
924
 
                set submit $form(submit)
925
 
                catch {lappend submit $form(submit_$item)}
926
 
                $item configure -command  \
927
 
                                [list HMsubmit_button $win $var(form_id) $form(param) \
928
 
                                $submit]
929
 
        }
930
 
 
931
 
        # process the reset button(s)
932
 
        HMinput_reset $win {}
933
 
        foreach item $form(reset_button) {
934
 
                $item configure -command $form(reset)
935
 
        }
936
 
 
937
 
        # unset all unused fields here
938
 
        unset form(reset) form(submit) form(reset_button) form(submit_button)
939
 
        unset var(form_id)
940
 
}
941
 
 
942
 
###################################################################
943
 
# handle form input items
944
 
# each item type is handled in a separate procedure
945
 
# Each "type" procedure needs to:
946
 
# - create the window
947
 
# - initialize it
948
 
# - add the "submit" and "reset" commands onto the proper Q's
949
 
#   "submit" is subst'd
950
 
#   "reset" is eval'd
951
 
 
952
 
proc HMtag_input {win param text} {
953
 
        upvar #0 HM$win var
954
 
 
955
 
        set type text   ;# the default
956
 
        HMextract_param $param type
957
 
        set type [string tolower $type]
958
 
        if {[catch {HMinput_$type $win $param} err]} {
959
 
                puts stderr $err
960
 
        }
961
 
}
962
 
 
963
 
# input type=text
964
 
# parameters NAME (reqd), MAXLENGTH, SIZE, VALUE
965
 
 
966
 
proc HMinput_text {win param {show {}}} {
967
 
        upvar #0 HM$win var
968
 
        upvar #0 $var(form_id) form
969
 
 
970
 
        # make the entry
971
 
        HMextract_param $param name             ;# required
972
 
        set item $win.input_text,$var(tags)
973
 
        set size 20; HMextract_param $param size
974
 
        set maxlength 0; HMextract_param $param maxlength
975
 
        entry $item -width $size -show $show
976
 
 
977
 
        # set the initial value
978
 
        set value ""; HMextract_param $param value
979
 
        $item insert 0 $value
980
 
                
981
 
        # insert the entry
982
 
        HMwin_install $win $item
983
 
 
984
 
        # set the "reset" and "submit" commands
985
 
        append form(reset) ";$item delete 0 end;$item insert 0 [list $value]"
986
 
        lappend form(submit) [list $name "\[$item get]"]
987
 
 
988
 
        # handle the maximum length (broken - no way to cleanup bindtags state)
989
 
        if {$maxlength} {
990
 
                bindtags $item "[bindtags $item] max$maxlength"
991
 
                bind max$maxlength <KeyPress> "%W delete $maxlength end"
992
 
        }
993
 
}
994
 
 
995
 
# password fields - same as text, only don't show data
996
 
# parameters NAME (reqd), MAXLENGTH, SIZE, VALUE
997
 
 
998
 
proc HMinput_password {win param} {
999
 
        HMinput_text $win $param *
1000
 
}
1001
 
 
1002
 
# checkbuttons are missing a "get" option, so we must use a global
1003
 
# variable to store the value.
1004
 
# Parameters NAME, VALUE, (reqd), CHECKED
1005
 
 
1006
 
proc HMinput_checkbox {win param} {
1007
 
        upvar #0 HM$win var
1008
 
        upvar #0 $var(form_id) form
1009
 
 
1010
 
        HMextract_param $param name
1011
 
        HMextract_param $param value
1012
 
 
1013
 
        # Set the global variable, don't use the "form" alias as it is not
1014
 
        # defined in the global scope of the button
1015
 
        set variable $var(form_id)(check_$var(tags))    
1016
 
        set item $win.input_checkbutton,$var(tags)
1017
 
        checkbutton $item -variable $variable -off {} -on $value -text "  "
1018
 
        if {[HMextract_param $param checked]} {
1019
 
                $item select
1020
 
                append form(reset) ";$item select"
1021
 
        } else {
1022
 
                append form(reset) ";$item deselect"
1023
 
        }
1024
 
 
1025
 
        HMwin_install $win $item
1026
 
        lappend form(submit) [list $name \$form(check_$var(tags))]
1027
 
}
1028
 
 
1029
 
# radio buttons.  These are like check buttons, but only one can be selected
1030
 
 
1031
 
proc HMinput_radio {win param} {
1032
 
        upvar #0 HM$win var
1033
 
        upvar #0 $var(form_id) form
1034
 
 
1035
 
        HMextract_param $param name
1036
 
        HMextract_param $param value
1037
 
 
1038
 
        set first [expr ![info exists form(radio_$name)]]
1039
 
        set variable $var(form_id)(radio_$name)
1040
 
        set variable $var(form_id)(radio_$name)
1041
 
        set item $win.input_radiobutton,$var(tags)
1042
 
        radiobutton $item -variable $variable -value $value -text " "
1043
 
 
1044
 
        HMwin_install $win $item
1045
 
 
1046
 
        if {$first || [HMextract_param $param checked]} {
1047
 
                $item select
1048
 
                append form(reset) ";$item select"
1049
 
        } else {
1050
 
                append form(reset) ";$item deselect"
1051
 
        }
1052
 
 
1053
 
        # do the "submit" actions in /form so we only end up with 1 per button grouping
1054
 
        # contributing to the submission
1055
 
}
1056
 
 
1057
 
# hidden fields, just append to the "submit" data
1058
 
# params: NAME, VALUE (reqd)
1059
 
 
1060
 
proc HMinput_hidden {win param} {
1061
 
        upvar #0 HM$win var
1062
 
        upvar #0 $var(form_id) form
1063
 
        HMextract_param $param name
1064
 
        HMextract_param $param value
1065
 
        lappend form(submit) [list $name $value]
1066
 
}
1067
 
 
1068
 
# handle input images.  The spec isn't very clear on these, so I'm not
1069
 
# sure its quite right
1070
 
# Use std image tag, only set up our own callbacks
1071
 
#  (e.g. make sure ismap isn't set)
1072
 
# params: NAME, SRC (reqd) ALIGN
1073
 
 
1074
 
proc HMinput_image {win param} {
1075
 
        upvar #0 HM$win var
1076
 
        upvar #0 $var(form_id) form
1077
 
        HMextract_param $param name
1078
 
        set name                ;# barf if no name is specified
1079
 
        set item [HMtag_img $win $param {}]
1080
 
        $item configure -relief raised -bd 2 -bg blue
1081
 
 
1082
 
        # make a dummy "submit" button, and invoke it to send the form.
1083
 
        # We have to get the %x,%y in the value somehow, so calculate it during
1084
 
        # binding, and save it in the form array for later processing
1085
 
 
1086
 
        set submit $win.dummy_submit,$var(tags)
1087
 
        if {[winfo exists $submit]} {
1088
 
                destroy $submit
1089
 
        }
1090
 
        button $submit  -takefocus 0;# this never gets mapped!
1091
 
        lappend form(submit_button) $submit
1092
 
        set form(submit_$submit) [list $name $name.\$form(X).\$form(Y)]
1093
 
        
1094
 
        $item configure -takefocus 1
1095
 
        bind $item <FocusIn> "catch \{$win see $item\}"
1096
 
        bind $item <1> "$item configure -relief sunken"
1097
 
        bind $item <Return> "
1098
 
                set $var(form_id)(X) 0
1099
 
                set $var(form_id)(Y) 0
1100
 
                $submit invoke  
1101
 
        "
1102
 
        bind $item <ButtonRelease-1> "
1103
 
                set $var(form_id)(X) %x
1104
 
                set $var(form_id)(Y) %y
1105
 
                $item configure -relief raised
1106
 
                $submit invoke  
1107
 
        "
1108
 
}
1109
 
 
1110
 
# Set up the reset button.  Wait for the /form to attach
1111
 
# the -command option.  There could be more that 1 reset button
1112
 
# params VALUE
1113
 
 
1114
 
proc HMinput_reset {win param} {
1115
 
        upvar #0 HM$win var
1116
 
        upvar #0 $var(form_id) form
1117
 
 
1118
 
        set value reset
1119
 
        HMextract_param $param value
1120
 
 
1121
 
        set item $win.input_reset,$var(tags)
1122
 
        button $item -text [HMmap_esc $value] -cursor left_ptr
1123
 
        HMwin_install $win $item
1124
 
        lappend form(reset_button) $item
1125
 
}
1126
 
 
1127
 
# Set up the submit button.  Wait for the /form to attach
1128
 
# the -command option.  There could be more that 1 submit button
1129
 
# params: NAME, VALUE
1130
 
 
1131
 
proc HMinput_submit {win param} {
1132
 
        upvar #0 HM$win var
1133
 
        upvar #0 $var(form_id) form
1134
 
 
1135
 
        HMextract_param $param name
1136
 
        set value submit
1137
 
        HMextract_param $param value
1138
 
        set item $win.input_submit,$var(tags)
1139
 
        button $item -text [HMmap_esc $value] -fg blue -cursor left_ptr
1140
 
        HMwin_install $win $item
1141
 
        lappend form(submit_button) $item
1142
 
        # need to tie the "name=value" to this button
1143
 
        # save the pair and do it when we finish the submit button
1144
 
        catch {set form(submit_$item) [list $name $value]}
1145
 
}
1146
 
 
1147
 
#########################################################################
1148
 
# selection items
1149
 
# They all go into a list box.  We don't what to do with the listbox until
1150
 
# we know how many items end up in it.  Gather up the data for the "options"
1151
 
# and finish up in the /select tag
1152
 
# params: NAME (reqd), MULTIPLE, SIZE 
1153
 
 
1154
 
proc HMtag_select {win param text} {
1155
 
        upvar #0 HM$win var
1156
 
        upvar #0 $var(form_id) form
1157
 
 
1158
 
        HMextract_param $param name
1159
 
        set size 5;  HMextract_param $param size
1160
 
        set form(select_size) $size
1161
 
        set form(select_name) $name
1162
 
        set form(select_values) ""              ;# list of values to submit
1163
 
        if {[HMextract_param $param multiple]} {
1164
 
                set mode multiple
1165
 
        } else {
1166
 
                set mode single
1167
 
        }
1168
 
        set item $win.select,$var(tags)
1169
 
    frame $item
1170
 
    set form(select_frame) $item
1171
 
        listbox $item.list -selectmode $mode -width 0 -exportselection 0 -cursor left_ptr
1172
 
        HMwin_install $win $item
1173
 
}
1174
 
 
1175
 
# select options
1176
 
# The values returned in the query may be different from those
1177
 
# displayed in the listbox, so we need to keep a separate list of
1178
 
# query values.
1179
 
#  form(select_default) - contains the default query value
1180
 
#  form(select_frame) - name of the listbox's containing frame
1181
 
#  form(select_values)  - list of query values
1182
 
# params: VALUE, SELECTED
1183
 
 
1184
 
proc HMtag_option {win param text} {
1185
 
        upvar #0 HM$win var
1186
 
        upvar #0 $var(form_id) form
1187
 
        upvar $text data
1188
 
        set frame $form(select_frame)
1189
 
 
1190
 
        # set default option (or options)
1191
 
        if {[HMextract_param $param selected]} {
1192
 
        lappend form(select_default) [$form(select_frame).list size]
1193
 
    }
1194
 
    set value [string trimright $data " \n"]
1195
 
    $frame.list insert end $value
1196
 
        HMextract_param $param value
1197
 
        lappend form(select_values) $value
1198
 
        set data ""
1199
 
}
1200
 
 
1201
 
# do most of the work here!
1202
 
# if SIZE>1, make the listbox.  Otherwise make a "drop-down"
1203
 
# listbox with a label in it
1204
 
# If the # of items > size, add a scroll bar
1205
 
# This should probably be broken up into callbacks to make it
1206
 
# easier to override the "look".
1207
 
 
1208
 
proc HMtag_/select {win param text} {
1209
 
        upvar #0 HM$win var
1210
 
        upvar #0 $var(form_id) form
1211
 
        set frame $form(select_frame)
1212
 
        set size $form(select_size)
1213
 
        set items [$frame.list size]
1214
 
 
1215
 
        # set the defaults and reset button
1216
 
        append form(reset) ";$frame.list selection clear 0  $items"
1217
 
        if {[info exists form(select_default)]} {
1218
 
                foreach i $form(select_default) {
1219
 
                        $frame.list selection set $i
1220
 
                        append form(reset) ";$frame.list selection set $i"
1221
 
                }
1222
 
        } else {
1223
 
                $frame.list selection set 0
1224
 
                append form(reset) ";$frame.list selection set 0"
1225
 
        }
1226
 
 
1227
 
        # set up the submit button. This is the general case.  For single
1228
 
        # selections we could be smarter
1229
 
 
1230
 
        for {set i 0} {$i < $size} {incr i} {
1231
 
                set value [format {[expr {[%s selection includes %s] ? {%s} : {}}]} \
1232
 
                                $frame.list $i [lindex $form(select_values) $i]]
1233
 
                lappend form(submit) [list $form(select_name) $value]
1234
 
        }
1235
 
        
1236
 
        # show the listbox - no scroll bar
1237
 
 
1238
 
        if {$size > 1 && $items <= $size} {
1239
 
                $frame.list configure -height $items
1240
 
                pack $frame.list
1241
 
 
1242
 
        # Listbox with scrollbar
1243
 
 
1244
 
        } elseif {$size > 1} {
1245
 
                scrollbar $frame.scroll -command "$frame.list yview"  \
1246
 
                                -orient v -takefocus 0
1247
 
                $frame.list configure -height $size \
1248
 
                        -yscrollcommand "$frame.scroll set"
1249
 
                pack $frame.list $frame.scroll -side right -fill y
1250
 
 
1251
 
        # This is a joke!
1252
 
 
1253
 
        } else {
1254
 
                scrollbar $frame.scroll -command "$frame.list yview"  \
1255
 
                        -orient h -takefocus 0
1256
 
                $frame.list configure -height 1 \
1257
 
                        -yscrollcommand "$frame.scroll set"
1258
 
                pack $frame.list $frame.scroll -side top -fill x
1259
 
        }
1260
 
 
1261
 
        # cleanup
1262
 
 
1263
 
        foreach i [array names form select_*] {
1264
 
                unset form($i)
1265
 
        }
1266
 
}
1267
 
 
1268
 
# do a text area (multi-line text)
1269
 
# params: COLS, NAME, ROWS (all reqd, but default rows and cols anyway)
1270
 
 
1271
 
proc HMtag_textarea {win param text} {
1272
 
        upvar #0 HM$win var
1273
 
        upvar #0 $var(form_id) form
1274
 
        upvar $text data
1275
 
 
1276
 
        set rows 5; HMextract_param $param rows
1277
 
        set cols 30; HMextract_param $param cols
1278
 
        HMextract_param $param name
1279
 
        set item $win.textarea,$var(tags)
1280
 
        frame $item
1281
 
        text $item.text -width $cols -height $rows -wrap none \
1282
 
                        -yscrollcommand "$item.scroll set" -padx 3 -pady 3
1283
 
        scrollbar $item.scroll -command "$item.text yview"  -orient v
1284
 
        $item.text insert 1.0 $data
1285
 
        HMwin_install $win $item
1286
 
        pack $item.text $item.scroll -side right -fill y
1287
 
        lappend form(submit) [list $name "\[$item.text get 0.0 end]"]
1288
 
        append form(reset) ";$item.text delete 1.0 end; \
1289
 
                        $item.text insert 1.0 [list $data]"
1290
 
        set data ""
1291
 
}
1292
 
 
1293
 
# procedure to install windows into the text widget
1294
 
# - win:  name of the text widget
1295
 
# - item: name of widget to install
1296
 
 
1297
 
proc HMwin_install {win item} {
1298
 
        upvar #0 HM$win var
1299
 
        $win window create $var(S_insert) -window $item -align bottom
1300
 
        $win tag add indent$var(level) $item
1301
 
        set focus [expr {[winfo class $item] != "Frame"}]
1302
 
        $item configure -takefocus $focus
1303
 
        bind $item <FocusIn> "$win see $item"
1304
 
}
1305
 
 
1306
 
#####################################################################
1307
 
# Assemble and submit the query
1308
 
# each list element in "stuff" is a name/value pair
1309
 
# - The names are the NAME parameters of the various fields
1310
 
# - The values get run through "subst" to extract the values
1311
 
# - We do the user callback with the list of name value pairs
1312
 
 
1313
 
proc HMsubmit_button {win form_id param stuff} {
1314
 
        upvar #0 HM$win var
1315
 
        upvar #0 $form_id form
1316
 
        set query ""
1317
 
        foreach pair $stuff {
1318
 
                set value [subst [lindex $pair 1]]
1319
 
                #if {$value != ""} {
1320
 
                        set item [lindex $pair 0]
1321
 
                        lappend query $item $value
1322
 
                #}
1323
 
        }
1324
 
        # this is the user callback.
1325
 
        HMsubmit_form $win $param $query
1326
 
}
1327
 
 
1328
 
# sample user callback for form submission
1329
 
# should be replaced by the application
1330
 
# Sample version generates a string suitable for http
1331
 
 
1332
 
proc HMsubmit_form {win param query} {
1333
 
        set result ""
1334
 
        set sep ""
1335
 
        foreach i $query {
1336
 
                append result  $sep [HMmap_reply $i]
1337
 
                if {$sep != "="} {set sep =} {set sep &}
1338
 
        }
1339
 
        puts $result
1340
 
}
1341
 
 
1342
 
# do x-www-urlencoded character mapping
1343
 
# The spec says: "non-alphanumeric characters are replaced by '%HH'"
1344
 
 
1345
 
set HMalphanumeric      a-zA-Z0-9       ;# definition of alphanumeric character class
1346
 
for {set i 1} {$i <= 256} {incr i} {
1347
 
    set c [format %c $i]
1348
 
    if {![string match \[$HMalphanumeric\] $c]} {
1349
 
        set HMform_map($c) %[format %.2x $i]
1350
 
    }
1351
 
}
1352
 
 
1353
 
# These are handled specially
1354
 
array set HMform_map {
1355
 
    " " +   \n %0d%0a
1356
 
}
1357
 
 
1358
 
# 1 leave alphanumerics characters alone
1359
 
# 2 Convert every other character to an array lookup
1360
 
# 3 Escape constructs that are "special" to the tcl parser
1361
 
# 4 "subst" the result, doing all the array substitutions
1362
 
 
1363
 
proc HMmap_reply {string} {
1364
 
    global HMform_map HMalphanumeric
1365
 
    regsub -all \[^$HMalphanumeric\] $string {$HMform_map(&)} string
1366
 
    regsub -all \n $string {\\n} string
1367
 
    regsub -all \t $string {\\t} string
1368
 
    regsub -all {[][{})\\]\)} $string {\\&} string
1369
 
    return [subst $string]
1370
 
}
1371
 
 
1372
 
# convert a x-www-urlencoded string int a a list of name/value pairs
1373
 
 
1374
 
# 1  convert a=b&c=d... to {a} {b} {c} {d}...
1375
 
# 2, convert + to  " "
1376
 
# 3, convert %xx to char equiv
1377
 
 
1378
 
proc HMcgiDecode {data} {
1379
 
        set data [split $data "&="]
1380
 
        foreach i $data {
1381
 
                lappend result [cgiMap $i]
1382
 
        }
1383
 
        return $result
1384
 
}
1385
 
 
1386
 
proc HMcgiMap {data} {
1387
 
        regsub -all {\+} $data " " data
1388
 
        
1389
 
        if {[regexp % $data]} {
1390
 
                regsub -all {([][$\\])} $data {\\\1} data
1391
 
                regsub -all {%([0-9a-fA-F][0-9a-fA-F])} $data  {[format %c 0x\1]} data
1392
 
                return [subst $data]
1393
 
        } else {
1394
 
                return $data
1395
 
        }
1396
 
}
1397
 
 
1398
 
# There is a bug in the tcl library focus routines that prevents focus
1399
 
# from every reaching an un-viewable window.  Use our *own*
1400
 
# version of the library routine, until the bug is fixed, make sure we
1401
 
# over-ride the library version, and not the otherway around
1402
 
 
1403
 
auto_load tkFocusOK
1404
 
proc tkFocusOK w {
1405
 
    set code [catch {$w cget -takefocus} value]
1406
 
    if {($code == 0) && ($value != "")} {
1407
 
    if {$value == 0} {
1408
 
        return 0
1409
 
    } elseif {$value == 1} {
1410
 
        return 1
1411
 
    } else {
1412
 
        set value [uplevel #0 $value $w]
1413
 
        if {$value != ""} {
1414
 
        return $value
1415
 
        }
1416
 
    }
1417
 
    }
1418
 
    set code [catch {$w cget -state} value]
1419
 
    if {($code == 0) && ($value == "disabled")} {
1420
 
    return 0
1421
 
    }
1422
 
    regexp Key|Focus "[bind $w] [bind [winfo class $w]]"
1423
 
}