Tk Library Source Code

Check-in [f68c45cec8]
Login

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

Overview
Comment:Mentry: Updated for version 4.5. See the ChangeLog for details.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: f68c45cec8314351a48d602de2024daa729284a22aacf33fb013c72405a32d40
User & Date: csaba 2025-05-21 18:28:35.656
Context
2025-05-23
19:44
Tablelist: Made the column deletion by orders of magnitude faster. check-in: 941b5bfe92 user: csaba tags: trunk
2025-05-21
18:28
Mentry: Updated for version 4.5. See the ChangeLog for details. check-in: f68c45cec8 user: csaba tags: trunk
18:16
Wcb: Updated for version 4.2. See the ChangeLog for details. check-in: 48048ea4d3 user: csaba tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Added examples/mentry/frankingid.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
#! /usr/bin/env tclsh

#==============================================================================
# Demonstrates how to implement a multi-entry widget for 20-character
# Franking IDs used by the German postal service (Deutsche Post) for tracking
# and sorting mail pieces.  Franking IDs are usually written as strings of the
# form "XX XXXX XXXX XX XXXX XXXX", where each X is an uppercase hexadecimal
# digit and the last one is a CRC checksum of type CCITT (CRC-4).
#
# Copyright (c) 2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

package require Tk
package require mentry

set title "Franking ID"
wm title . $title

#
# Add some entries to the Tk option database
#
source [file join [file dirname [info script]] option.tcl]

#------------------------------------------------------------------------------
# frankingIdMentry
#
# Creates a new mentry widget win that allows to display and edit 20-character
# Franking IDs.  Sets the type attribute of the widget to FrankingId and
# returns the name of the newly created widget.
#------------------------------------------------------------------------------
proc frankingIdMentry {win args} {
    #
    # Create a mentry widget consisting of 6 entries of widths 2, 4, 4, 2, 4,
    # and 4, separated by " " characters, and set its type to FrankingId
    #
    eval [list mentry::mentry $win] $args
    $win configure -body {2 " " 4 " " 4 " " 2 " " 4 " " 4}
    $win attrib type FrankingId

    #
    # Install automatic uppercase conversion and allow only hexadecimal
    # digits in all entry components; use wcb::cbappend (or wcb::cbprepend)
    # instead of wcb::callback in order to keep the wcb::checkEntryLen
    # callback, registered by mentry::mentry for all entry components
    #
    for {set n 0} {$n < 6} {incr n} {
	set w [$win entrypath $n]
	wcb::cbappend $w before insert wcb::convStrToUpper \
		      {wcb::checkStrForRegExp {^[0-9A-F]*$}}
	$win adjustentry $n "0123456789ABCDEF"
	bindtags $w [linsert [bindtags $w] 1 MentryFrankingId]
    }

    return $win
}

#------------------------------------------------------------------------------
# putFrankingId
#
# Outputs the Franking ID id to the mentry widget win of type FrankingId.  The
# Franking ID must be either a string consisting of 20 uppercase hexadecimal
# digits, or a string of the form "XX XXXX XXXX XX XXXX XXXX", where each X is
# an uppercase hexadecimal digit.
#------------------------------------------------------------------------------
proc putFrankingId {id win} {
    #
    # Check the syntax of num
    #
    set expr1 {^[0-9A-F]{20}$}
    set expr2 {^[0-9A-F]{2} [0-9A-F]{4} [0-9A-F]{4} [0-9A-F]{2} [0-9A-F]{4}\
		[0-9A-F]{4}$}
    if {[regexp $expr1 $id]} {
	set isFormatted 0
    } elseif {[regexp $expr2 $id]} {
	set isFormatted 1
    } else {
	return -code error "expected a Franking ID but got \"$id\""
    }

    #
    # Check the widget and display the properly formatted Franking ID
    #
    checkIfFrankingIdMentry $win
    if {$isFormatted} {
	foreach {str0 str1 str2 str3 str4 str5} [split $id " "] {}
	$win put 0 $str0 $str1 $str2 $str3 $str4 $str5
    } else {
	$win put 0 [string range $id 0 1] [string range $id 2 5] \
		   [string range $id 6 9] [string range $id 10 11] \
		   [string range $id 12 15] [string range $id 16 19]
    }
}

#------------------------------------------------------------------------------
# getFrankingId
#
# Returns the Franking ID contained in the mentry widget win of type
# FrankingId, per default formatted as a string of the form
# "XX XXXX XXXX XX XXXX XXXX", where each X is an uppercase hexadecimal digit.
#------------------------------------------------------------------------------
proc getFrankingId {win {formatted 1}} {
    #
    # Check the widget
    #
    checkIfFrankingIdMentry $win

    #
    # Generate an error if any entry component is empty or incomplete.
    # "Incomplete" means in case of the last entry that it has less than
    # 3 characters, and in case of the other entries that it is not full.
    #
    for {set n 0} {$n < 6} {incr n} {
	if {[$win isempty $n]} {
	    focus [$win entrypath $n]
	    return -code error EMPTY
	}

	if {$n == 5} {
	    set w [$win entrypath $n]
	    if {[string length [$w get]] < 3} {
		focus $w
		return -code error INCOMPL
	    }
	} elseif {![$win isfull $n]} {
	    focus [$win entrypath $n]
	    return -code error INCOMPL
	}
    }

    #
    # Return the Franking ID built from the values contained in
    # the entry components and extended by the checksum if needed
    #
    set id [$win getstring]
    if {[string length $id] == 24} {  ;# i.e., last entry contains 3 characters
	append id [crc4 $id]
    } elseif {[string index $id end] ne [crc4 [string range $id 0 end-1]]} {
	focus $w
	return -code error BAD_CRC
    }
    return [expr {$formatted ? $id : [string map {" " ""} $id]}]
}

#------------------------------------------------------------------------------
# checkIfFrankingIdMentry
#
# Generates an error if win is not a mentry widget of type FrankingId.
#------------------------------------------------------------------------------
proc checkIfFrankingIdMentry win {
    if {![winfo exists $win]} {
	return -code error "bad window path name \"$win\""
    }

    if {[winfo class $win] ne "Mentry" || [$win attrib type] ne "FrankingId"} {
	return -code error \
	       "window \"$win\" is not a mentry widget for Franking IDs"
    }
}

#------------------------------------------------------------------------------
# crc4
#
# Returns the CRC-4 checksum of the specified string as an uppercase
# hexadecimal digit.  It is assumed that the string contains ASCII characters
# only.  Space characters (" ") are ignored.  Translated from C# code published
# by ub_coding at the bottom of the page
# https://stackoverflow.com/questions/46971887/crc-4-implementation-for-c-sharp.
#------------------------------------------------------------------------------
proc crc4 str {
    set crc 0
    set poly [expr {0x13 << 3}]			;# 10011000: x**4 + x + 1

    foreach char [split $str ""] {
	if {$char eq " "} {
	    continue
	}

	set code [scan $char %c]
	set crc [expr {$crc ^ $code}]

	for {set n 0} {$n < 8} {incr n} {
	    if {($crc & 0x80) != 0} {
		set crc [expr {$crc ^ $poly}]
	    }

	    set crc [expr {$crc << 1}]
	}
    }

    set crc [expr {$crc >> 4}]
    return [format %X $crc]
}

bind MentryFrankingId <<Paste>> { pasteFrankingId %W }

#------------------------------------------------------------------------------
# pasteFrankingId
#
# Handles <<Paste>> events in the entry component w of a mentry widget for
# Franking IDs by pasting the current contents of the clipboard into the mentry
# if it is a valid Franking ID.
#------------------------------------------------------------------------------
proc pasteFrankingId w {
    set res [catch {::tk::GetSelection $w CLIPBOARD} id]
    if {$res == 0} {
	set win [winfo parent $w]
	catch { putFrankingId $id $win }
    }

    return -code break ""
}

#------------------------------------------------------------------------------

#
# Frame .f with a mentry displaying a Franking ID
#
frame .f
label .f.l -text "A mentry widget for Franking IDs,\nwith automatic\
		  uppercase conversion:"
frankingIdMentry .f.me -justify center
pack .f.l .f.me

#
# Message strings corresponding to the values
# returned by getFrankingId on failure
#
array set msgs {
    EMPTY	"Field value missing"
    INCOMPL	"Incomplete field value"
    BAD_CRC	"Bad CRC-4 checksum"
}

#
# Button .get invoking the procedure getFrankingId
#
button .get -text "Get from mentry" -command {
    if {[catch {
	set id ""
	set id [getFrankingId .f.me]
    } result] != 0} {
	bell
	tk_messageBox -icon error -message $msgs($result) \
		      -title $title -type ok
    }
}

#
# Label .id displaying the result of getFrankingId
#
label .id -textvariable id

#
# Frame .sep and button .close
#
frame .sep -height 2 -bd 1 -relief sunken
button .close -text Close -command exit

#
# Manage the widgets
#
pack .close -side bottom -pady 7p
pack .sep -side bottom -fill x
pack .f -padx 7p -pady 7p
pack .get -padx 7p
pack .id -padx 7p -pady 7p

putFrankingId "36 2FCA 2870 4D 2003 0394" .f.me
focus [.f.me entrypath 0]
Added examples/mentry/frankingid_tile.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
#! /usr/bin/env tclsh

#==============================================================================
# Demonstrates how to implement a multi-entry widget for 20-character
# Franking IDs used by the German postal service (Deutsche Post) for tracking
# and sorting mail pieces.  Franking IDs are usually written as strings of the
# form "XX XXXX XXXX XX XXXX XXXX", where each X is an uppercase hexadecimal
# digit and the last one is a CRC checksum of type CCITT (CRC-4).
#
# Copyright (c) 2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

package require Tk
package require mentry_tile

set title "Franking ID"
wm title . $title

#
# Add some entries to the Tk option database
#
source [file join [file dirname [info script]] option_tile.tcl]

#------------------------------------------------------------------------------
# frankingIdMentry
#
# Creates a new mentry widget win that allows to display and edit 20-character
# Franking IDs.  Sets the type attribute of the widget to FrankingId and
# returns the name of the newly created widget.
#------------------------------------------------------------------------------
proc frankingIdMentry {win args} {
    #
    # Create a mentry widget consisting of 6 entries of widths 2, 4, 4, 2, 4,
    # and 4, separated by " " characters, and set its type to FrankingId
    #
    eval [list mentry::mentry $win] $args
    $win configure -body {2 " " 4 " " 4 " " 2 " " 4 " " 4}
    $win attrib type FrankingId

    #
    # Install automatic uppercase conversion and allow only hexadecimal
    # digits in all entry components; use wcb::cbappend (or wcb::cbprepend)
    # instead of wcb::callback in order to keep the wcb::checkEntryLen
    # callback, registered by mentry::mentry for all entry components
    #
    for {set n 0} {$n < 6} {incr n} {
	set w [$win entrypath $n]
	wcb::cbappend $w before insert wcb::convStrToUpper \
		      {wcb::checkStrForRegExp {^[0-9A-F]*$}}
	$win adjustentry $n "0123456789ABCDEF"
	bindtags $w [linsert [bindtags $w] 1 MentryFrankingId]
    }

    return $win
}

#------------------------------------------------------------------------------
# putFrankingId
#
# Outputs the Franking ID id to the mentry widget win of type Franking ID.  The
# Franking ID must be either a string consisting of 20 uppercase hexadecimal
# digits, or a string of the form "XX XXXX XXXX XX XXXX XXXX", where each X is
# an uppercase hexadecimal digit.
#------------------------------------------------------------------------------
proc putFrankingId {id win} {
    #
    # Check the syntax of num
    #
    set expr1 {^[0-9A-F]{20}$}
    set expr2 {^[0-9A-F]{2} [0-9A-F]{4} [0-9A-F]{4} [0-9A-F]{2} [0-9A-F]{4}\
		[0-9A-F]{4}$}
    if {[regexp $expr1 $id]} {
	set isFormatted 0
    } elseif {[regexp $expr2 $id]} {
	set isFormatted 1
    } else {
	return -code error "expected a Franking ID but got \"$id\""
    }

    #
    # Check the widget and display the properly formatted Franking ID
    #
    checkIfFrankingIdMentry $win
    if {$isFormatted} {
	foreach {str0 str1 str2 str3 str4 str5} [split $id " "] {}
	$win put 0 $str0 $str1 $str2 $str3 $str4 $str5
    } else {
	$win put 0 [string range $id 0 1] [string range $id 2 5] \
		   [string range $id 6 9] [string range $id 10 11] \
		   [string range $id 12 15] [string range $id 16 19]
    }
}

#------------------------------------------------------------------------------
# getFrankingId
#
# Returns the Franking ID contained in the mentry widget win of type
# FrankingId, per default formatted as a string of the form
# "XX XXXX XXXX XX XXXX XXXX", where each X is an uppercase hexadecimal digit.
#------------------------------------------------------------------------------
proc getFrankingId {win {formatted 1}} {
    #
    # Check the widget
    #
    checkIfFrankingIdMentry $win

    #
    # Generate an error if any entry component is empty or incomplete.
    # "Incomplete" means in case of the last entry that it has less than
    # 3 characters, and in case of the other entries that it is not full.
    #
    for {set n 0} {$n < 6} {incr n} {
	if {[$win isempty $n]} {
	    focus [$win entrypath $n]
	    return -code error EMPTY
	}

	if {$n == 5} {
	    set w [$win entrypath $n]
	    if {[string length [$w get]] < 3} {
		focus $w
		return -code error INCOMPL
	    }
	} elseif {![$win isfull $n]} {
	    focus [$win entrypath $n]
	    return -code error INCOMPL
	}
    }

    #
    # Return the Franking ID built from the values contained in
    # the entry components and extended by the checksum if needed
    #
    set id [$win getstring]
    if {[string length $id] == 24} {  ;# i.e., last entry contains 3 characters
	append id [crc4 $id]
    } elseif {[string index $id end] ne [crc4 [string range $id 0 end-1]]} {
	focus $w
	return -code error BAD_CRC
    }
    return [expr {$formatted ? $id : [string map {" " ""} $id]}]
}

#------------------------------------------------------------------------------
# checkIfFrankingIdMentry
#
# Generates an error if win is not a mentry widget of type FrankingId.
#------------------------------------------------------------------------------
proc checkIfFrankingIdMentry win {
    if {![winfo exists $win]} {
	return -code error "bad window path name \"$win\""
    }

    if {[winfo class $win] ne "Mentry" || [$win attrib type] ne "FrankingId"} {
	return -code error \
	       "window \"$win\" is not a mentry widget for Franking IDs"
    }
}

#------------------------------------------------------------------------------
# crc4
#
# Returns the CRC-4 checksum of the specified string as an uppercase
# hexadecimal digit.  It is assumed that the string contains ASCII characters
# only.  Space characters (" ") are ignored.  Translated from C# code published
# by ub_coding at the bottom of the page
# https://stackoverflow.com/questions/46971887/crc-4-implementation-for-c-sharp.
#------------------------------------------------------------------------------
proc crc4 str {
    set crc 0
    set poly [expr {0x13 << 3}]			;# 10011000: x**4 + x + 1

    foreach char [split $str ""] {
	if {$char eq " "} {
	    continue
	}

	set code [scan $char %c]
	set crc [expr {$crc ^ $code}]

	for {set n 0} {$n < 8} {incr n} {
	    if {($crc & 0x80) != 0} {
		set crc [expr {$crc ^ $poly}]
	    }

	    set crc [expr {$crc << 1}]
	}
    }

    set crc [expr {$crc >> 4}]
    return [format %X $crc]
}

bind MentryFrankingId <<Paste>> { pasteFrankingId %W }

#------------------------------------------------------------------------------
# pasteFrankingId
#
# Handles <<Paste>> events in the entry component w of a mentry widget for
# Franking IDs by pasting the current contents of the clipboard into the mentry
# if it is a valid Franking ID.
#------------------------------------------------------------------------------
proc pasteFrankingId w {
    set res [catch {::tk::GetSelection $w CLIPBOARD} id]
    if {$res == 0} {
	set win [winfo parent [winfo parent $w]]
	catch { putFrankingId $id $win }
    }

    return -code break ""
}

#------------------------------------------------------------------------------

#
# Improve the window's appearance by using a tile
# frame as a container for the other widgets
#
ttk::frame .base

#
# Frame .base.f with a mentry displaying a Franking ID
#
ttk::frame .base.f
ttk::label .base.f.l -text "A mentry widget for Franking IDs,\nwith automatic\
			    uppercase conversion:"
frankingIdMentry .base.f.me -justify center
pack .base.f.l .base.f.me

#
# Message strings corresponding to the values
# returned by getFrankingId on failure
#
array set msgs {
    EMPTY	"Field value missing"
    INCOMPL	"Incomplete field value"
    BAD_CRC	"Bad CRC-4 checksum"
}

#
# Button .base.get invoking the procedure getFrankingId
#
ttk::button .base.get -text "Get from mentry" -command {
    if {[catch {
	set id ""
	set id [getFrankingId .base.f.me]
    } result] != 0} {
	bell
	tk_messageBox -icon error -message $msgs($result) \
		      -title $title -type ok
    }
}

#
# Label .base.id displaying the result of getFrankingId
#
ttk::label .base.id -textvariable id

#
# Separator .base.sep and button .base.close
#
ttk::separator .base.sep -orient horizontal
ttk::button .base.close -text Close -command exit

#
# Manage the widgets
#
pack .base.close -side bottom -pady 7p
pack .base.sep -side bottom -fill x
pack .base.f -padx 7p -pady 7p
pack .base.get -padx 7p
pack .base.id -padx 7p -pady 7p
pack .base -expand yes -fill both

putFrankingId "36 2FCA 2870 4D 2003 0394" .base.f.me
focus [.base.f.me entrypath 0]
Changes to modules/mentry/CHANGES.txt.
1
2
















3
4
5
6
7
8
9
What is new in Mentry 4.4?
--------------------------

















1. Included the same version 2.24 of the mega-widget utility package
   mwutil as in the most recent Tablelist, Scrollutil, and Tsw releases.

2. Minor improvements in the documentation.

What was new in Mentry 4.3.1?
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
What is new in Mentry 4.5?
--------------------------

1. Included the same version 2.25 of the mega-widget utility package
   mwutil as in the most recent Tablelist, Scrollutil, and Tsw releases.

2. Added a new demo script (and its tile-based version) implementing a
   multi-entry widget for 20-character Franking IDs used by the German
   postal service (thanks to Ralf Richard Goebel for his proposal).

3. Included a description of the new demo script in the Mentry
   Programmer's Guide.

4. Improved the documentation, mainly by extending the CSS stylesheet
   used in the HTML files.

What was new in Mentry 4.4?
---------------------------

1. Included the same version 2.24 of the mega-widget utility package
   mwutil as in the most recent Tablelist, Scrollutil, and Tsw releases.

2. Minor improvements in the documentation.

What was new in Mentry 4.3.1?
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
4. Included the same version 2.17 of the general mega-widget utility
   module "mwutil.tcl" as in the most recent Tablelist release 6.11.

5. For current Tk versions Mentry no longer requires that changing the
   theme be done using the "ttk::setTheme" command instead of
   "ttk::style theme use", which was necessary for older tile versions.

6. Made the demo-scripts scaling-aware.  In addition, with Tk 8.6.10 or
   later, they now fully support the Dark Mode appearance on Mac OS
   10.14 and later.

7. Reworked the invocations of "package vcompare", taking into account
   that Tcl versions earlier than 8.5 did not support the letters "a"
   and "b" in version numbers (thanks to Mike Walsh for his bug report).








|







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
4. Included the same version 2.17 of the general mega-widget utility
   module "mwutil.tcl" as in the most recent Tablelist release 6.11.

5. For current Tk versions Mentry no longer requires that changing the
   theme be done using the "ttk::setTheme" command instead of
   "ttk::style theme use", which was necessary for older tile versions.

6. Made the demo scripts scaling-aware.  In addition, with Tk 8.6.10 or
   later, they now fully support the Dark Mode appearance on Mac OS
   10.14 and later.

7. Reworked the invocations of "package vcompare", taking into account
   that Tcl versions earlier than 8.5 did not support the letters "a"
   and "b" in version numbers (thanks to Mike Walsh for his bug report).

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

2. Adapted to some changes in future Tcl and Tk releases (for example,
   made sure that it works with Tcl 9.0 and Tk 8.7).

3. Included the same version of the general mega-widget utility module
   "mwutil.tcl" as in the most recent Tablelist release 6.3.

4. Updated the demo-scripts and the documentation.

5. Several code improvements and minor bug fixes.

What was new in Mentry 3.7?
---------------------------

1. Minor performance improvements.







|







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

2. Adapted to some changes in future Tcl and Tk releases (for example,
   made sure that it works with Tcl 9.0 and Tk 8.7).

3. Included the same version of the general mega-widget utility module
   "mwutil.tcl" as in the most recent Tablelist release 6.3.

4. Updated the demo scripts and the documentation.

5. Several code improvements and minor bug fixes.

What was new in Mentry 3.7?
---------------------------

1. Minor performance improvements.
Changes to modules/mentry/COPYRIGHT.txt.
1
2
3
4
5
6
7
8
Multi-entry widget package Mentry, version 4.4
Copyright (c) 1999-2025  Csaba Nemethi (E-mail: [email protected])

This library is free software; you can use, modify, and redistribute it
for any purpose, provided that existing copyright notices are retained
in all copies and that this notice is included verbatim in any
distributions.

|







1
2
3
4
5
6
7
8
Multi-entry widget package Mentry, version 4.5
Copyright (c) 1999-2025  Csaba Nemethi (E-mail: [email protected])

This library is free software; you can use, modify, and redistribute it
for any purpose, provided that existing copyright notices are retained
in all copies and that this notice is included verbatim in any
distributions.

Changes to modules/mentry/ChangeLog.




















1
2
3
4
5
6
7




















2025-03-24  Csaba Nemethi <[email protected]>

	* Released Mentry 4.4.

2025-03-22  Csaba Nemethi <[email protected]>

	* *.tcl:         Bumped the version number to 4.4.
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2025-05-21  Csaba Nemethi <[email protected]>

	* *.tcl:         Bumped the version number to 4.5.
	* COPYRIGHT.txt:
	* README.txt:

	* CHANGES.txt: Updated to reflect the changes.
	* doc/*.html:

	* scripts/mwutil/*.tcl: Extended the mwutil package.

	* doc/frankingid.png: Added new screenshot.

	* doc/stylesheet.css: Extended the CSS stylesheet.

	* doc/wcbRef.html: Updated to the version included in Wcb 4.2.

	* ../../examples/mentry/frankingid.tcl:      Added new demo scripts.
	* ../../examples/mentry/frankingid_tile.tcl:

2025-03-24  Csaba Nemethi <[email protected]>

	* Released Mentry 4.4.

2025-03-22  Csaba Nemethi <[email protected]>

	* *.tcl:         Bumped the version number to 4.4.
Changes to modules/mentry/README.txt.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

  - the implementation of the multi-entry mega-widget "mentry",
    including a general utility module for mega-widgets;
  - procedures that facilitate the use of multi-entry widgets for
    displaying and editing date and time in a great variety of formats,
    real numbers in fixed-point format, as well as IP(v4) addresses and
    IPv6 addresses;
  - two richly commented demo scripts containing the typical steps
    needed to create and handle a mentry widget for a particular
    purpose;
  - two demo scripts that show how to use the date- and time-related
    procedures;
  - tile-based counterparts of the above-mentioned demo scripts;
  - a tutorial in HTML format;
  - reference pages in HTML format.







|







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

  - the implementation of the multi-entry mega-widget "mentry",
    including a general utility module for mega-widgets;
  - procedures that facilitate the use of multi-entry widgets for
    displaying and editing date and time in a great variety of formats,
    real numbers in fixed-point format, as well as IP(v4) addresses and
    IPv6 addresses;
  - three richly commented demo scripts containing the typical steps
    needed to create and handle a mentry widget for a particular
    purpose;
  - two demo scripts that show how to use the date- and time-related
    procedures;
  - tile-based counterparts of the above-mentioned demo scripts;
  - a tutorial in HTML format;
  - reference pages in HTML format.
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

    https://www.nemethi.de

How to Get It?
--------------

Mentry is available for free download from the same URL as Wcb.  The
distribution file is "mentry4.4.tar.gz" for UNIX and "mentry4_4.zip" for
Windows.  These files contain the same information, except for the
additional carriage return character preceding the linefeed at the end
of each line in the text files for Windows.

Mentry is also included in tklib, which has the address

    https://core.tcl.tk/tklib

How to Install It?
------------------

Install the package as a subdirectory of one of the directories given
by the "auto_path" variable.  For example, you can install it as a
subdirectory of the "lib" directory within your Tcl/Tk installation.

To install Mentry on UNIX, "cd" to the desired directory and unpack the
distribution file "mentry4.4.tar.gz":

    gunzip -c mentry4.4.tar.gz | tar -xf -

On most UNIX systems this can be replaced with

    tar -zxf mentry4.4.tar.gz

Both commands will create a directory named "mentry4.4", with the
subdirectories "demos", "doc", and "scripts".

On Windows, use WinZip or some other program capable of unpacking the
distribution file "mentry4_4.zip" into the directory "mentry4.4", with
the subdirectories "demos", "doc", and "scripts".

The file "mentryThemes.tcl" in the "scripts" directory is only needed
for applications using the Mentry_tile package (see next section).

How to Use It?
--------------







|
















|

|



|

|



|







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

    https://www.nemethi.de

How to Get It?
--------------

Mentry is available for free download from the same URL as Wcb.  The
distribution file is "mentry4.5.tar.gz" for UNIX and "mentry4_5.zip" for
Windows.  These files contain the same information, except for the
additional carriage return character preceding the linefeed at the end
of each line in the text files for Windows.

Mentry is also included in tklib, which has the address

    https://core.tcl.tk/tklib

How to Install It?
------------------

Install the package as a subdirectory of one of the directories given
by the "auto_path" variable.  For example, you can install it as a
subdirectory of the "lib" directory within your Tcl/Tk installation.

To install Mentry on UNIX, "cd" to the desired directory and unpack the
distribution file "mentry4.5.tar.gz":

    gunzip -c mentry4.5.tar.gz | tar -xf -

On most UNIX systems this can be replaced with

    tar -zxf mentry4.5.tar.gz

Both commands will create a directory named "mentry4.5", with the
subdirectories "demos", "doc", and "scripts".

On Windows, use WinZip or some other program capable of unpacking the
distribution file "mentry4_5.zip" into the directory "mentry4.5", with
the subdirectories "demos", "doc", and "scripts".

The file "mentryThemes.tcl" in the "scripts" directory is only needed
for applications using the Mentry_tile package (see next section).

How to Use It?
--------------
Added modules/mentry/doc/frankingid.png.

cannot compute difference between binary files

Changes to modules/mentry/doc/index.html.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
  <title>The Multi-Entry Widget Package Mentry 4.4</title>

  <meta name="Author" content="Csaba Nemethi">
  <meta name="Keywords" content="mentry, widget, entry, label">

  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>The Multi-Entry Widget Package Mentry 4.4</h1>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>



|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
  <title>The Multi-Entry Widget Package Mentry 4.5</title>

  <meta name="Author" content="Csaba Nemethi">
  <meta name="Keywords" content="mentry, widget, entry, label">

  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>The Multi-Entry Widget Package Mentry 4.5</h1>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
Changes to modules/mentry/doc/mentry.html.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Mentry Programmer's Guide</h1>

    <h2>For Mentry Version 4.4</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Mentry Programmer's Guide</h1>

    <h2>For Mentry Version 4.5</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
45
46
47
48
49
50
51


52
53
54
55
56
57
58
  <h4><a href="#examples">Examples</a></h4>

  <ul>
    <li><a href="#ex_phoneNumber">A mentry Widget for Phone Numbers</a></li>

    <li><a href="#ex_ethernetAddr">A mentry Widget for Ethernet
    Addresses</a></li>



    <li><a href="#ex_dateTime">Using mentry Widgets for Date and Time</a></li>

    <li><a href="#ex_tile">Tile-Based Demo Scripts</a></li>
  </ul>

  <div>







>
>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  <h4><a href="#examples">Examples</a></h4>

  <ul>
    <li><a href="#ex_phoneNumber">A mentry Widget for Phone Numbers</a></li>

    <li><a href="#ex_ethernetAddr">A mentry Widget for Ethernet
    Addresses</a></li>

    <li><a href="#ex_frankingId">A mentry Widget for Franking IDs</a></li>

    <li><a href="#ex_dateTime">Using mentry Widgets for Date and Time</a></li>

    <li><a href="#ex_tile">Tile-Based Demo Scripts</a></li>
  </ul>

  <div>
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

    <li>procedures that facilitate the use of multi-entry widgets for
    displaying and editing <a href="mentryDateTime.html">date and time</a> in a
    great variety of formats, <a href="mentryFixedPoint.html">real numbers in
    fixed-point format</a>, as well as <a href="mentryIPAddr.html">IP(v4)
    addresses</a> and <a href="mentryIPv6Addr.html">IPv6 addresses</a>;</li>

    <li>two richly commented demo scripts containing the typical steps needed
    to create and handle a mentry widget for a particular purpose;</li>

    <li>two demo scripts that show how to use the date- and time-related
    procedures;</li>

    <li>tile-based counterparts of the above-mentioned demo scripts;</li>








|







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

    <li>procedures that facilitate the use of multi-entry widgets for
    displaying and editing <a href="mentryDateTime.html">date and time</a> in a
    great variety of formats, <a href="mentryFixedPoint.html">real numbers in
    fixed-point format</a>, as well as <a href="mentryIPAddr.html">IP(v4)
    addresses</a> and <a href="mentryIPv6Addr.html">IPv6 addresses</a>;</li>

    <li>three richly commented demo scripts containing the typical steps needed
    to create and handle a mentry widget for a particular purpose;</li>

    <li>two demo scripts that show how to use the date- and time-related
    procedures;</li>

    <li>tile-based counterparts of the above-mentioned demo scripts;</li>

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
  <p>you can make sure that the three entries will only accept numeric input,
  thus providing a comfortable and safe user interface for editing 10-digit
  phone numbers.</p>

  <h3 id="ov_get">How to Get It?</h3>

  <p>Mentry is available for free download from the same URL as Wcb.&nbsp; The
  distribution file is <code>mentry4.4.tar.gz</code> for UNIX and
  <code>mentry4_4.zip</code> for Windows.&nbsp; These files contain the same
  information, except for the additional carriage return character preceding
  the linefeed at the end of each line in the text files for Windows.</p>

  <p>Mentry is also included in tklib, which has the address</p>

  <blockquote>
    <address>
      <a href="https://core.tcl.tk/tklib">https://core.tcl.tk/tklib</a>
    </address>
  </blockquote>

  <h3 id="ov_install">How to Install It?</h3>

  <p>Install the package as a subdirectory of one of the directories given by
  the <code>auto_path</code> variable.&nbsp; For example, you can install it as
  a subdirectory of the <code>lib</code> directory within your Tcl/Tk
  installation.</p>

  <p>To install Mentry <i>on UNIX</i>, <code>cd</code> to the desired directory
  and unpack the distribution file <code>mentry4.4.tar.gz</code>:</p>

  <blockquote>
    <pre>
gunzip -c mentry4.4.tar.gz | tar -xf -
</pre>
  </blockquote>

  <p>On most UNIX systems this can be replaced with</p>

  <blockquote>
    <pre>
tar -zxf mentry4.4.tar.gz
</pre>
  </blockquote>

  <p>Both commands will create a directory named <code>mentry4.4</code>, with
  the subdirectories <code>demos</code>, <code>doc</code>, and
  <code>scripts</code>.</p>

  <p><i>On Windows</i>, use WinZip or some other program capable of unpacking
  the distribution file <code>mentry4_4.zip</code> into the directory
  <code>mentry4.4</code>, with the subdirectories <code>demos</code>,
  <code>doc</code>, and <code>scripts</code>.</p>

  <p>The file <code>mentryThemes.tcl</code> in the <code>scripts</code>
  directory is only needed for applications using the Mentry_tile package (see
  next section).</p>

  <p>Notice that in tklib the Mentry <code>demos</code> directory is replaced







|
|



















|



|







|



|




|
|







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
  <p>you can make sure that the three entries will only accept numeric input,
  thus providing a comfortable and safe user interface for editing 10-digit
  phone numbers.</p>

  <h3 id="ov_get">How to Get It?</h3>

  <p>Mentry is available for free download from the same URL as Wcb.&nbsp; The
  distribution file is <code>mentry4.5.tar.gz</code> for UNIX and
  <code>mentry4_5.zip</code> for Windows.&nbsp; These files contain the same
  information, except for the additional carriage return character preceding
  the linefeed at the end of each line in the text files for Windows.</p>

  <p>Mentry is also included in tklib, which has the address</p>

  <blockquote>
    <address>
      <a href="https://core.tcl.tk/tklib">https://core.tcl.tk/tklib</a>
    </address>
  </blockquote>

  <h3 id="ov_install">How to Install It?</h3>

  <p>Install the package as a subdirectory of one of the directories given by
  the <code>auto_path</code> variable.&nbsp; For example, you can install it as
  a subdirectory of the <code>lib</code> directory within your Tcl/Tk
  installation.</p>

  <p>To install Mentry <i>on UNIX</i>, <code>cd</code> to the desired directory
  and unpack the distribution file <code>mentry4.5.tar.gz</code>:</p>

  <blockquote>
    <pre>
gunzip -c mentry4.5.tar.gz | tar -xf -
</pre>
  </blockquote>

  <p>On most UNIX systems this can be replaced with</p>

  <blockquote>
    <pre>
tar -zxf mentry4.5.tar.gz
</pre>
  </blockquote>

  <p>Both commands will create a directory named <code>mentry4.5</code>, with
  the subdirectories <code>demos</code>, <code>doc</code>, and
  <code>scripts</code>.</p>

  <p><i>On Windows</i>, use WinZip or some other program capable of unpacking
  the distribution file <code>mentry4_5.zip</code> into the directory
  <code>mentry4.5</code>, with the subdirectories <code>demos</code>,
  <code>doc</code>, and <code>scripts</code>.</p>

  <p>The file <code>mentryThemes.tcl</code> in the <code>scripts</code>
  directory is only needed for applications using the Mentry_tile package (see
  next section).</p>

  <p>Notice that in tklib the Mentry <code>demos</code> directory is replaced
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
  <code>&lt;&lt;Paste&gt;&gt;</code> (<code>&lt;Control-v&gt;</code> or
  <code>&lt;Command-v&gt;</code>) events in these entry widgets by pasting the
  current contents of the clipboard into the mentry, provided that it is a
  valid 10-digit phone number:</p>

  <blockquote>
    <pre>
bind MentryPhoneNumber <<Paste>> { pastePhoneNumber %W }

<span class="cmt">#------------------------------------------------------------------------------
# pastePhoneNumber
#
# Handles <<Paste>> events in the entry component w of a mentry widget for
# 10-digit phone numbers by pasting the current contents of the clipboard into
# the mentry if it is a valid 10-digit phone number.
#------------------------------------------------------------------------------</span>
proc pastePhoneNumber w {
    set res [catch {::tk::GetSelection $w CLIPBOARD} num]
    if {$res == 0} {
        set win [winfo parent $w]







|




|







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
  <code>&lt;&lt;Paste&gt;&gt;</code> (<code>&lt;Control-v&gt;</code> or
  <code>&lt;Command-v&gt;</code>) events in these entry widgets by pasting the
  current contents of the clipboard into the mentry, provided that it is a
  valid 10-digit phone number:</p>

  <blockquote>
    <pre>
bind MentryPhoneNumber &lt;&lt;Paste&gt;&gt; { pastePhoneNumber %W }

<span class="cmt">#------------------------------------------------------------------------------
# pastePhoneNumber
#
# Handles &lt;&lt;Paste&gt;&gt; events in the entry component w of a mentry widget for
# 10-digit phone numbers by pasting the current contents of the clipboard into
# the mentry if it is a valid 10-digit phone number.
#------------------------------------------------------------------------------</span>
proc pastePhoneNumber w {
    set res [catch {::tk::GetSelection $w CLIPBOARD} num]
    if {$res == 0} {
        set win [winfo parent $w]
853
854
855
856
857
858
859
860
861
862
863
864
865











































































































































































866
867
868
869
870
871
872
            0x$strs(0) 0x$strs(1) 0x$strs(2) 0x$strs(3) 0x$strs(4) 0x$strs(5)]
}
</pre>
  </blockquote>

  <p>We will not show the rest of the code here, because it is very similar to
  the one presented in the preceding section.&nbsp; The mentry widget for
  Ethernet addresses looks like in the following figure:</p>

  <blockquote>
    <img src="ethernetaddr.png" alt="Ethernet Address" width="303"
    height="272">
  </blockquote>












































































































































































  <h3 id="ex_dateTime">Using mentry Widgets for Date and Time</h3>

  <p>Multi-entry widgets can be used to display and edit date and time in a
  great variety of formats.&nbsp; The Mentry package contains ready-to-use
  commands for this purpose:</p>








|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
            0x$strs(0) 0x$strs(1) 0x$strs(2) 0x$strs(3) 0x$strs(4) 0x$strs(5)]
}
</pre>
  </blockquote>

  <p>We will not show the rest of the code here, because it is very similar to
  the one presented in the preceding section.&nbsp; The mentry widget for
  Ethernet addresses looks like in the following screenshot:</p>

  <blockquote>
    <img src="ethernetaddr.png" alt="Ethernet Address" width="303"
    height="272">
  </blockquote>

  <h3 id="ex_frankingId">A mentry Widget for Franking IDs</h3>

  <p>The German postal service (Deutsche Post) uses 20-character Franking IDs
  for tracking and sorting mail pieces.&nbsp; Franking IDs are usually written
  as strings of the form <code>"XX XXXX XXXX XX XXXX XXXX"</code>, where each
  <code>"X"</code> is an uppercase hexadecimal digit and the last one is a CRC
  checksum of type CCITT (CRC-4).&nbsp; The file <code>frankingid.tcl</code> in
  the <code>demos</code> directory contains the steps needed to create and use
  a multi-entry widget for displaying and editing Franking IDs.&nbsp; It
  implements the main procedures <code>frankingIdMentry</code>,
  <code>putFrankingId</code>, and <code>getFrankingId</code>, along with the
  helper ones <code>checkIfFrankingIdMentry</code>, <code>crc4</code>, and
  <code>pasteFrankingId</code>.</p>

  <p>The procedure <code>frankingIdMentry</code>, which creates a mentry widget
  for Franking IDs, is implemented as follows:</p>

  <blockquote>
    <pre>
<span class="cmt">#------------------------------------------------------------------------------
# frankingIdMentry
#
# Creates a new mentry widget win that allows to display and edit 20-character
# Franking IDs.  Sets the type attribute of the widget to FrankingId and
# returns the name of the newly created widget.
#------------------------------------------------------------------------------</span>
proc frankingIdMentry {win args} {
    <span class="cmt">#
    # Create a mentry widget consisting of 6 entries of widths 2, 4, 4, 2, 4,
    # and 4, separated by " " characters, and set its type to FrankingId
    #</span>
    eval [list mentry::mentry $win] $args
    $win configure -body {2 " " 4 " " 4 " " 2 " " 4 " " 4}
    $win attrib type FrankingId

    <span class="cmt">#
    # Install automatic uppercase conversion and allow only hexadecimal
    # digits in all entry components; use wcb::cbappend (or wcb::cbprepend)
    # instead of wcb::callback in order to keep the wcb::checkEntryLen
    # callback, registered by mentry::mentry for all entry components
    #</span>
    for {set n 0} {$n < 6} {incr n} {
        set w [$win entrypath $n]
        wcb::cbappend $w before insert wcb::convStrToUpper \
                      {wcb::checkStrForRegExp {^[0-9A-F]*$}}
        $win adjustentry $n "0123456789ABCDEF"
        bindtags $w [linsert [bindtags $w] 1 MentryFrankingId]
    }

    return $win
}
</pre>
  </blockquote>

  <p>The procedure <code>putFrankingId</code> accepts as its first argument
  both an unformatted (20-character) Franking ID and one of the form
  <code>"XX XXXX XXXX XX XXXX XXXX"</code>:</p>

  <blockquote>
    <pre>
<span class="cmt">#------------------------------------------------------------------------------
# putFrankingId
#
# Outputs the Franking ID id to the mentry widget win of type FrankingId.  The
# Franking ID must be either a string consisting of 20 uppercase hexadecimal
# digits, or a string of the form "XX XXXX XXXX XX XXXX XXXX", where each X is
# an uppercase hexadecimal digit.
#------------------------------------------------------------------------------</span>
proc putFrankingId {id win} {
    <span class="cmt">#
    # Check the syntax of num
    #</span>
    set expr1 {^[0-9A-F]{20}$}
    set expr2 {^[0-9A-F]{2} [0-9A-F]{4} [0-9A-F]{4} [0-9A-F]{2} [0-9A-F]{4}\
                [0-9A-F]{4}$}
    if {[regexp $expr1 $id]} {
        set isFormatted 0
    } elseif {[regexp $expr2 $id]} {
        set isFormatted 1
    } else {
        return -code error "expected a Franking ID but got \"$id\""
    }

    <span class="cmt">#
    # Check the widget and display the properly formatted Franking ID
    #</span>
    checkIfFrankingIdMentry $win
    if {$isFormatted} {
        foreach {str0 str1 str2 str3 str4 str5} [split $id " "] {}
        $win put 0 $str0 $str1 $str2 $str3 $str4 $str5
    } else {
        $win put 0 [string range $id 0 1] [string range $id 2 5] \
                   [string range $id 6 9] [string range $id 10 11] \
                   [string range $id 12 15] [string range $id 16 19]
    }
}
</pre>
  </blockquote>

  <p>Likewise, the Franking ID returned by the procedure
  <code>getFrankingId</code> can be a formatted or unformatted one, depending
  on the boolean value of its optional argument:</p>

  <blockquote>
    <pre>
<span class="cmt">#------------------------------------------------------------------------------
# getFrankingId
#
# Returns the Franking ID contained in the mentry widget win of type
# FrankingId, per default formatted as a string of the form
# "XX XXXX XXXX XX XXXX XXXX", where each X is an uppercase hexadecimal digit.
#------------------------------------------------------------------------------</span>
proc getFrankingId {win {formatted 1}} {
    <span class="cmt">#
    # Check the widget
    #</span>
    checkIfFrankingIdMentry $win

    <span class="cmt">#
    # Generate an error if any entry component is empty or incomplete.
    # "Incomplete" means in case of the last entry that it has less than
    # 3 characters, and in case of the other entries that it is not full.
    #</span>
    for {set n 0} {$n < 6} {incr n} {
        if {[$win isempty $n]} {
            focus [$win entrypath $n]
            return -code error EMPTY
        }

        if {$n == 5} {
            set w [$win entrypath $n]
            if {[string length [$w get]] < 3} {
                focus $w
                return -code error INCOMPL
            }
        } elseif {![$win isfull $n]} {
            focus [$win entrypath $n]
            return -code error INCOMPL
        }
    }

    <span class="cmt">#
    # Return the Franking ID built from the values contained in
    # the entry components and extended by the checksum if needed
    #</span>
    set id [$win getstring]
    if {[string length $id] == 24} {  ;<span class="cmt"># i.e., last entry contains 3 characters</span>
        append id [crc4 $id]
    } elseif {[string index $id end] ne [crc4 [string range $id 0 end-1]]} {
        focus $w
        return -code error BAD_CRC
    }
    return [expr {$formatted ? $id : [string map {" " ""} $id]}]
}
</pre>
  </blockquote>

  <p>As seen in the code above, if the last entry contains 3 characters only
  then the procedure computes the checksum and appends it to the result.&nbsp;
  Otherwise it checks whether the last character equals the checksum built from
  the first 24 characters (of which only 19 are significant), and raises an
  error if this is not the case.&nbsp; (Note that the checksum algorithm
  ignores the space characters.)</p>

  <p>Again, we will not show the rest of the code here.&nbsp; The mentry widget
  for Franking IDs looks like in the following screenshot:</p>

  <blockquote>
    <img src="frankingid.png" alt="Franking ID" width="283" height="272">
  </blockquote>

  <h3 id="ex_dateTime">Using mentry Widgets for Date and Time</h3>

  <p>Multi-entry widgets can be used to display and edit date and time in a
  great variety of formats.&nbsp; The Mentry package contains ready-to-use
  commands for this purpose:</p>

Changes to modules/mentry/doc/mentryDateTime.html.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Multi-Entry Widgets for Date and Time</h1>

    <h2>For Mentry Version 4.4</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Multi-Entry Widgets for Date and Time</h1>

    <h2>For Mentry Version 4.5</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
Changes to modules/mentry/doc/mentryFixedPoint.html.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</head>

<body>
  <div>
    <h1>Multi-Entry Widgets for Real Numbers<br>
    in Fixed-Point Format</h1>

    <h2>For Mentry Version 4.4</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</head>

<body>
  <div>
    <h1>Multi-Entry Widgets for Real Numbers<br>
    in Fixed-Point Format</h1>

    <h2>For Mentry Version 4.5</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
Changes to modules/mentry/doc/mentryIPAddr.html.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Multi-Entry Widgets for IP Addresses</h1>

    <h2>For Mentry Version 4.4</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Multi-Entry Widgets for IP Addresses</h1>

    <h2>For Mentry Version 4.5</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
Changes to modules/mentry/doc/mentryIPv6Addr.html.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Multi-Entry Widgets for IPv6 Addresses</h1>

    <h2>For Mentry Version 4.4</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Multi-Entry Widgets for IPv6 Addresses</h1>

    <h2>For Mentry Version 4.5</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
Changes to modules/mentry/doc/mentryThemes.html.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Commands Related to Tile Themes</h1>

    <h2>For Mentry Version 4.4</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>Commands Related to Tile Themes</h1>

    <h2>For Mentry Version 4.5</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
Changes to modules/mentry/doc/mentryWidget.html.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>The <code><b>mentry::mentry</b></code> Command</h1>

    <h2>For Mentry Version 4.4</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div>
    <h1>The <code><b>mentry::mentry</b></code> Command</h1>

    <h2>For Mentry Version 4.5</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
Changes to modules/mentry/doc/stylesheet.css.
1
2










3
4
5
6
7
8
9
10
11
12

13
14
15

16
17
18
19
20
/* generic class defining a top margin whose height equals the font size */
.tm {margin-top: 1em}











/* background, border, border-radius, and padding for the <pre> tag */
pre {
  background: #F7F7F7;
  border: silver solid 1px;
  border-radius: 4px;
  padding: 4px;
}

/* background for the <body> tag */

body {background: #FFFFFF}

/* text-align for the <div> tag */

div {text-align: center}

/* color for the <span> tag */
span.red {color: #E00000}
span.cmt {color: #36648b}


>
>
>
>
>
>
>
>
>
>









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

26
27
28



/* generic class defining a top margin whose height equals the font size */
.tm {margin-top: 1em}

/* text-align for the <div> tag */
div {text-align: center}

/* background for the <body> tag */
body {background: #FFFFFF}

/* color for the <span> tag */
span.red {color: #E00000}
span.cmt {color: #36648b}

/* background, border, border-radius, and padding for the <pre> tag */
pre {
  background: #F7F7F7;
  border: silver solid 1px;
  border-radius: 4px;
  padding: 4px;
}

/* background, border, border-radius, and padding for the <code> tag */
code {
  background: #F7F7F7;
  border: #F0F0F0 solid 1px;

  border-radius: 3px;
  padding: 2px;
}



Changes to modules/mentry/doc/wcbRef.html.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div align="center">
    <h1>Wcb Command Reference</h1>

    <h2>For Wcb Version 4.1</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  <link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>

<body>
  <div align="center">
    <h1>Wcb Command Reference</h1>

    <h2>For Wcb Version 4.2</h2>

    <h3>by</h3>

    <h2>Csaba Nemethi</h2>

    <address>
      <a href="mailto:[email protected]">[email protected]</a>
Changes to modules/mentry/mentry.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
#==============================================================================
# Main Mentry package module.
#
# Copyright (c) 1999-2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

package require -exact mentry::common 4.4

package provide mentry $mentry::version
package provide Mentry $mentry::version

mentry::useTile 0
mentry::createBindings






|






1
2
3
4
5
6
7
8
9
10
11
12
13
#==============================================================================
# Main Mentry package module.
#
# Copyright (c) 1999-2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

package require -exact mentry::common 4.5

package provide mentry $mentry::version
package provide Mentry $mentry::version

mentry::useTile 0
mentry::createBindings
Changes to modules/mentry/mentryCommon.tcl.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
	}
    }
    loadWcb

    #
    # Public variables:
    #
    variable version	4.4
    variable library	[file dirname [file normalize [info script]]]

    #
    # Creates a new multi-entry widget:
    #
    namespace export	mentry








|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
	}
    }
    loadWcb

    #
    # Public variables:
    #
    variable version	4.5
    variable library	[file dirname [file normalize [info script]]]

    #
    # Creates a new multi-entry widget:
    #
    namespace export	mentry

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

#
# Load the package mwutil from the directory "scripts/mwutil".  Take into
# account that it is also included in Scrollutil, Tablelist, and Tsw.
#
proc mentry::loadUtil {} {
    if {[catch {package present mwutil} version] == 0 &&
	[package vcompare $version 2.24] < 0} {
	package forget mwutil
    }
    package require mwutil 2.24[-]
}
mentry::loadUtil







|


|


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

#
# Load the package mwutil from the directory "scripts/mwutil".  Take into
# account that it is also included in Scrollutil, Tablelist, and Tsw.
#
proc mentry::loadUtil {} {
    if {[catch {package present mwutil} version] == 0 &&
	[package vcompare $version 2.25] < 0} {
	package forget mwutil
    }
    package require mwutil 2.25[-]
}
mentry::loadUtil
Changes to modules/mentry/mentry_tile.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#==============================================================================
# Main Mentry_tile package module.
#
# Copyright (c) 1999-2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

package require -exact mentry::common 4.4

if {$::tk_version < 8.5 || [regexp {^8\.5a[1-5]$} $::tk_patchLevel]} {
    package require tile 0.6[mentry::-]
}

package provide mentry_tile $mentry::version
package provide Mentry_tile $mentry::version






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
#==============================================================================
# Main Mentry_tile package module.
#
# Copyright (c) 1999-2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

package require -exact mentry::common 4.5

if {$::tk_version < 8.5 || [regexp {^8\.5a[1-5]$} $::tk_patchLevel]} {
    package require tile 0.6[mentry::-]
}

package provide mentry_tile $mentry::version
package provide Mentry_tile $mentry::version
Changes to modules/mentry/pkgIndex.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
#==============================================================================
# Mentry and Mentry_tile package index file.
#
# Copyright (c) 1999-2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

#
# Regular packages:
#
package ifneeded mentry         4.4 \
	[list source [file join $dir mentry.tcl]]
package ifneeded mentry_tile    4.4 \
	[list source [file join $dir mentry_tile.tcl]]

#
# Aliases:
#
package ifneeded Mentry         4.4 \
	[list package require -exact mentry      4.4]
package ifneeded Mentry_tile    4.4 \
	[list package require -exact mentry_tile 4.4]

#
# Code common to all packages:
#
package ifneeded mentry::common 4.4 \
	[list source [file join $dir mentryCommon.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
#==============================================================================
# Mentry and Mentry_tile package index file.
#
# Copyright (c) 1999-2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

#
# Regular packages:
#
package ifneeded mentry         4.5 \
	[list source [file join $dir mentry.tcl]]
package ifneeded mentry_tile    4.5 \
	[list source [file join $dir mentry_tile.tcl]]

#
# Aliases:
#
package ifneeded Mentry         4.5 \
	[list package require -exact mentry      4.5]
package ifneeded Mentry_tile    4.5 \
	[list package require -exact mentry_tile 4.5]

#
# Code common to all packages:
#
package ifneeded mentry::common 4.5 \
	[list source [file join $dir mentryCommon.tcl]]
Changes to modules/mentry/scripts/mwutil/mwutil.tcl.
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
# ========================
#

namespace eval mwutil {
    #
    # Public variables:
    #
    variable version	2.24
    variable library	[file dirname [file normalize [info script]]]

    #
    # Public procedures:
    #
    namespace export	wrongNumArgs getAncestorByClass convEventFields \
			defineKeyNav processTraversal focusNext focusPrev \
			configureWidget fullConfigOpt fullOpt enumOpts \
			configureSubCmd attribSubCmdEx attribSubCmd \
			hasattribSubCmdEx hasattribSubCmd unsetattribSubCmdEx \
			unsetattribSubCmd getScrollInfo getScrollInfo2 \
			isScrollable scrollByUnits genMouseWheelEvent \
			containsPointer hasFocus windowingSystem currentTheme \
			normalizeColor parsePadding

    #
    # Make modified versions of the procedures tk_focusNext and
    # tk_focusPrev, to be invoked in the processTraversal command
    #
    proc makeFocusProcs {} {
	#







|













|







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
# ========================
#

namespace eval mwutil {
    #
    # Public variables:
    #
    variable version	2.25
    variable library	[file dirname [file normalize [info script]]]

    #
    # Public procedures:
    #
    namespace export	wrongNumArgs getAncestorByClass convEventFields \
			defineKeyNav processTraversal focusNext focusPrev \
			configureWidget fullConfigOpt fullOpt enumOpts \
			configureSubCmd attribSubCmdEx attribSubCmd \
			hasattribSubCmdEx hasattribSubCmd unsetattribSubCmdEx \
			unsetattribSubCmd getScrollInfo getScrollInfo2 \
			isScrollable scrollByUnits genMouseWheelEvent \
			containsPointer hasFocus windowingSystem currentTheme \
			isColorLight normalizeColor parsePadding

    #
    # Make modified versions of the procedures tk_focusNext and
    # tk_focusPrev, to be invoked in the processTraversal command
    #
    proc makeFocusProcs {} {
	#
703
704
705
706
707
708
709













710
711
712
713
714
715
716
	return $::ttk::currentTheme
    } elseif {[info exists ::tile::currentTheme]} {
	return $::tile::currentTheme
    } else {
	return ""
    }
}














#------------------------------------------------------------------------------
# mwutil::normalizeColor
#
# Returns the representation of a given color in the form "#RRGGBB".
#------------------------------------------------------------------------------
proc mwutil::normalizeColor color {







>
>
>
>
>
>
>
>
>
>
>
>
>







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
	return $::ttk::currentTheme
    } elseif {[info exists ::tile::currentTheme]} {
	return $::tile::currentTheme
    } else {
	return ""
    }
}

#------------------------------------------------------------------------------
# mwutil::isColorLight
#
# A quick & dirty method to check whether a given color can be classified as
# light.  Inspired by article "Support Dark and Light themes in Win32 apps"
# (see https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/ui/
# apply-windows-themes).
#------------------------------------------------------------------------------
proc mwutil::isColorLight color {
    foreach {r g b} [winfo rgb . $color] {}
    return [expr {5 * ($g >> 8) + 2 * ($r >> 8) + ($b >> 8) > 8 * 128}]
}

#------------------------------------------------------------------------------
# mwutil::normalizeColor
#
# Returns the representation of a given color in the form "#RRGGBB".
#------------------------------------------------------------------------------
proc mwutil::normalizeColor color {
Changes to modules/mentry/scripts/mwutil/pkgIndex.tcl.
1
2
3
4
5
6
7
#==============================================================================
# mwutil package index file.
#
# Copyright (c) 2020-2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

package ifneeded mwutil 2.24 [list source [file join $dir mwutil.tcl]]






|
1
2
3
4
5
6
7
#==============================================================================
# mwutil package index file.
#
# Copyright (c) 2020-2025  Csaba Nemethi (E-mail: [email protected])
#==============================================================================

package ifneeded mwutil 2.25 [list source [file join $dir mwutil.tcl]]