exmh-2.9.0/0000755000170700017070000000000013370500011012003 5ustar valdisvaldisexmh-2.9.0/exmhcomp0000644000170700017070000000106713201227060013555 0ustar valdisvaldis#!/usr/bin/wish wm withdraw . set exmh_path /usr/local/bin set exmh_bin exmh # if exmh isn't running , start it up and wait till it's there before continuing if {[lsearch [winfo interps] $exmh_bin ]==-1} { exec $exmh_path/$exmh_bin -iconic 2>1 > /dev/null & while {[lsearch [winfo interps] $exmh_bin ]==-1} { after 200 } } if { 0 == [string length $argv] } { send exmh Msg_Compose exit 0 } else { if { 0 == [string first "mailto:" $argv 0] } { send exmh Msg_Mailto $argv } else { send exmh Msg_CompTo $argv } exit 0 } exmh-2.9.0/lib/0000755000170700017070000000000013201243213012552 5ustar valdisvaldisexmh-2.9.0/lib/fdispColor.tcl0000644000170700017070000001107413201227060015367 0ustar valdisvaldis# # fdispLabel.tcl # # This sets the color (or monochrome) feedback for the folder display area. # There are four states for a label, normal, unseen, target, current. # Each label has two parts, a box and text. # (Some labels can be bitmaps, in which case they just have a bitmap.) # You can read the TK man page on the canvas widget to see what # sort of looks are possible for text and rectangles. The defaults use # -fill color ;# for text color # -fill color ;# for box background # -outline color ;# for box outline color # -width number ;# for box outline width # -stipple bitmap ;# for box stipple pattern # # In turn, for color displays, there are 5 basic colors that can be set # by ~/.exmh_defaults # Resource Variable Comment # c_foreground $fdisp(c_fg) Foreground # c_background $fdisp(c_bg) Background # c_current $fdisp(c_current) Current folder # c_unseen $fdisp(c_unseen) Unseen messages in the folder # c_moved $fdisp(c_moved) Target folder / moved message # # For monochrome displays, the Canvas.foreground and Canvas.background # resources determine the foreground and background colors of the labels # # For consistency these colors are shared with the folder table of contents # display. If you find this limiting, wack away on the itemconfigures... # # Copyright (c) 1993 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. proc Fdisp_LabelConfigure { canvas } { global fdisp # # Note that a particular label may have multiple tags, so more than # one of these itemconfigures will hit. Therefore their ordering # is important, and you can play some tricks with combinations. # (more so on color displays) # Fdisp_FixupSpecials $canvas if {[winfo depth .] <= 4} { set fg [option get . c_foreground {}] set bg [option get . c_background {}] $canvas itemconfigure text -fill $fg $canvas itemconfigure box -fill $bg -width 1 -stipple {} -outline $fg $canvas itemconfigure bitmap -foreground $fg -background $bg $canvas itemconfigure unsntext -fill $fg $canvas itemconfigure unsnbox -width 3 -outline $fg $canvas itemconfigure unsnbitmap -foreground $bg -background $fg $canvas itemconfigure tartext -fill $fg $canvas itemconfigure tarbox -fill $fg -stipple gray25 $canvas itemconfigure tarbitmap -foreground $bg -background $fg $canvas itemconfigure curtext -fill $bg $canvas itemconfigure curbox -fill $fg -stipple {} $canvas itemconfigure curbitmap -foreground $bg -background $fg } else { $canvas itemconfigure text -fill $fdisp(c_fg) $canvas itemconfigure box -fill $fdisp(c_bg) \ -outline $fdisp(c_fg) -width 1 -stipple {} $canvas itemconfigure bitmap -foreground $fdisp(c_fg) \ -background $fdisp(c_bg) # Let current text be overridden by unseen & target feedback $canvas itemconfigure curtext -fill $fdisp(c_current) $canvas itemconfigure unsntext -fill $fdisp(c_unseenBg) $canvas itemconfigure unsnbox -fill $fdisp(c_unseen) $canvas itemconfigure unsnbox -outline $fdisp(c_unseen) -width 2 $canvas itemconfigure unsnbitmap -foreground $fdisp(c_unseen) \ -background $fdisp(c_bg) $canvas itemconfigure tartext -fill $fdisp(c_movedFg) $canvas itemconfigure tarbox -fill $fdisp(c_moved) $canvas itemconfigure tarbitmap -foreground $fdisp(c_moved) \ -background $fdisp(c_bg) $canvas itemconfigure curbox -outline $fdisp(c_current) -width 2 $canvas itemconfigure curbitmap -foreground $fdisp(c_current) \ -background $fdisp(c_bg) } } proc FdispClearHighlights { can } { global fdisp set canvas $fdisp($can) foreach tag [concat {unsnbitmap unsnbox unsntext} $fdisp(leafs,$can)] { $canvas dtag $tag } # The leaf tags cause ancestor nodes to be highlighted set fdisp(leafs,$can) {} # Deleting tags does not undo looks (like text widget!) # So we manually reset looks on the labels here. if {[winfo depth .] <= 4} { $canvas itemconfigure text -fill black $canvas itemconfigure box -fill white -width 1 -stipple {} $canvas itemconfigure bitmap -foreground black -background white } else { $canvas itemconfigure text -fill $fdisp(c_fg) $canvas itemconfigure box -fill $fdisp(c_bg) \ -outline $fdisp(c_fg) -width 1 -stipple {} $canvas itemconfigure bitmap -foreground $fdisp(c_fg) \ -background $fdisp(c_bg) } } exmh-2.9.0/lib/aliases.tcl0000644000170700017070000004230613201227060014706 0ustar valdisvaldis# aliases.tcl # Original contributed by Scott Stanton, sstanton@eng.sun.com # Tweaked for exmh integration by Brent Welch # # # Aliases_Pref: # # This procedure displays a dialog box for editing the MH aliases # file. # proc Aliases_Pref { {nalias {}} } { global mhProfile if ![info exists mhProfile(aliasfile)] { if {![AliasesInitProfile]} { return } } set filename [Mh_Pathname $mhProfile(aliasfile)] if ![file exists $filename] { if [catch {open $filename w} it] { Exmh_Status "Cannot create $filename\n$it" return } close $it } if [Exwin_Toplevel .aliaspref "Alias Browser" Alias] { .aliaspref.but.quit config -command {AliasesDismiss} wm protocol .aliaspref WM_DELETE_WINDOW AliasesDismiss Widget_AddBut .aliaspref.but save "Save" \ {Aliases_Save; Exwin_Dismiss .aliaspref} Widget_AddBut .aliaspref.but import "Import" \ {Aliases_Import} Widget_AddBut .aliaspref.but help "Help" \ {Aliases_Help} Widget_Label .aliaspref.but label {left fill} \ -text "MH Alias Definitions" frame .aliaspref.alias frame .aliaspref.addr pack .aliaspref.alias .aliaspref.addr -side left -fill both \ -padx 5 -pady 5 pack .aliaspref.addr -expand 1 Widget_ListEditor .aliaspref.alias Aliases alias \ Aliases_Insert Aliases_Change Aliases_Delete Address_Rebuild Widget_ListEditor .aliaspref.addr Addresses address \ Address_Insert Address_Change Address_Delete # Asymetric, but users can paste out of the Alias list, # and paste into the Address entry. .aliaspref.addr.listbox config -exportselection 0 # Create search bindings in the entries. bindtags .aliaspref.alias.entry \ [list .aliaspref.alias.entry Entry SearchAlias] bind SearchAlias \ {Widget_ListSearch .aliaspref.alias} bind .aliaspref.alias.entry { set alias [AliasesComplete .aliaspref.alias] Aliases_Insert break } bind .aliaspref.alias.entry \ {Aliases_Delete ; break} bindtags .aliaspref.addr.entry \ [list .aliaspref.addr.entry Entry SearchAddress] bind SearchAddress \ {Widget_ListSearch .aliaspref.addr} bind .aliaspref.addr.entry { set address [AliasesComplete .aliaspref.addr] break } foreach e {.aliaspref.alias.entry .aliaspref.addr.entry} { Exmh_Debug bindtags $e [bindtags $e] } wm minsize .aliaspref 1 1 } focus .aliaspref.alias.entry # The following command foils a spontaneous event # that otherwise kills the dialog in the special case that we # just created/destroyed the .aliasfile toplevel Visibility_Wait .aliaspref Aliases_Load Aliases_Rebuild $nalias } proc AliasesComplete { parent } { # Fetch the selected entry from the aliases listbox, if any Exmh_Status AliasesComplete set i [$parent.listbox curselection] if {$i != {}} { return [$parent.listbox get [lindex $i 0]] } else { return [$parent.entry get] } } proc Aliases_Help {} { Help Aliases "Tips for the Aliases interface" } # # AliasesInitProfile # # Create the MH profile entry that names the alias file. # proc AliasesInitProfile {} { global mhProfile aliasOK if [winfo exists .aliasfile] { return } Widget_Toplevel .aliasfile "Setup Alias File" Widget_Message .aliasfile msg -aspect 1000 -text " The MH aliases are kept in a file (you choose the name) and this file is named in the AliasFile profile entry. Should Exmh set that up for you now?" Widget_Frame .aliasfile rim Pad {top expand fill} .aliasfile.rim configure -bd 10 Widget_Label .aliasfile.rim l {left} -text "Alias file name: " Widget_Entry .aliasfile.rim e {left fill} -width 30 .aliasfile.rim.e insert 0 [glob ~]/.mh_aliases set aliasOK 0 Widget_Frame .aliasfile.rim but Menubar {top fill} Widget_AddBut .aliasfile.rim.but yes "Yes" [list AliasesSetupCommit .aliasfile .aliasfile.rim.e] Widget_AddBut .aliasfile.rim.but no "No" {destroy .aliasfile} tkwait window .aliasfile return $aliasOK } proc AliasesSetupCommit {top entry} { global mhProfile aliasOK set filename [$entry get] regsub -all "\[ \t\n\]" $filename {} filename if ![file exists $filename] { if [catch {open $filename w} it] { .aliasfile.msg config -text "Cannot create $filename\n$it" return } close $it } set mhProfile(aliasfile) $filename if [catch {open ~/.mh_profile a} out] { Exmh_Status "Cannot open ~/.mh_profile: $out" error unset mhProfile(aliasfile) destroy .aliasfile return } puts $out "AliasFile: $filename" Exmh_Status "AliasFile: $filename" close $out set aliasOK 1 destroy $top } # # Aliases_Rebuild: # # Load the aliases list into the alias listbox. If item is specified, # then that element of the list will be selected, otherwise no element # will be selected. # proc Aliases_Rebuild {{item {}}} { global aliases alias set top [.aliaspref.alias.listbox nearest 0] .aliaspref.alias.listbox delete 0 end set names [AliasesList] eval .aliaspref.alias.listbox insert end $names if {$item == {}} { .aliaspref.alias.listbox selection clear 0 end .aliaspref.alias.listbox see $top set alias {} } else { set index [lsearch -exact $names $item] .aliaspref.alias.listbox select set $index .aliaspref.alias.listbox see $index set alias $item } Address_Rebuild } proc AliasesList {} { global aliasesOrder set res {} foreach a $aliasesOrder { if [regexp {^[ ]*[;#]} $a] { continue } if [regexp {^[ ]*$} $a] { continue } if [regexp {^[ ]*<} $a] { continue } lappend res $a } return $res } # # Address_Rebuild: # # Display addresses from currently selected alias in the address listbox. # If item is specified, then that element of the list will be selected, # otherwise no element will be selected. # proc Address_Rebuild {{item {}}} { global aliases address alias # rebuild the address list based on the current alias selected if {([string length $alias] > 0) && [info exists aliases($alias)]} { .aliaspref.addr.listbox delete 0 end set names [lsort $aliases($alias)] eval .aliaspref.addr.listbox insert end $names } else { .aliaspref.addr.listbox delete 0 end set item {} } # now select appropriate item from the list if {$item == {}} { .aliaspref.addr.listbox selection clear 0 end } else { set index [lsearch -exact $names $item] .aliaspref.addr.listbox select set $index .aliaspref.addr.listbox see $index set address [.aliaspref.addr.listbox get $index] } } # # Aliases_New: # # Create a new alias. For use with message display window (maybe...) # Instead, what currently happens is that MsgShowInText side-effects # our address variable so the Aliases_Pref UI is updated. # proc Aliases_New { nalias naddress } { global aliases alias address if [info exists aliases($nalias)] { # Existing alias - invoke user interface Aliases_Pref $nalias set address $naddress set alias $nalias } else { AliasesDirty set aliases($alias) $naddress catch {Aliases_Rebuild $alias} } } # # Aliases_Insert: # # Add the specified entry to the alias list, if it is unique. # proc Aliases_Insert {} { global aliases alias address aliasesOrder if ![info exist aliases($alias)] { AliasesDirty lappend aliases($alias) $address lappend aliasesOrder $alias } else { # error, alias already exists } Aliases_Rebuild $alias } # # Aliases_Change: # # Change the name of specified alias. If the new name is already taken, # nothing changes. # proc Aliases_Change {} { global aliases alias aliasesOrder set current [.aliaspref.alias.listbox curselection] if {[llength $current] == 1} { set item [.aliaspref.alias.listbox get $current] if {![info exists aliases($alias)]} { set aliases($alias) $aliases($item) unset aliases($item) set ix [lsearch $aliasesOrder $item] set aliasesOrder [lreplace $aliasesOrder $ix $ix $alias] AliasesDirty Aliases_Rebuild $alias } } } # # Aliases_Delete: # # Delete the current selection from the list of aliases # proc Aliases_Delete {} { global aliases alias aliasesOrder if {[string length $alias] > 0} { set ix [lsearch $aliasesOrder $alias] if {$ix >= 0} { AliasesDirty set aliasesOrder [lreplace $aliasesOrder $ix $ix] catch {unset aliases($alias)} Aliases_Rebuild } } } # # Address_Insert: # # Add the specified entry to the address list. Duplicates are allowed. # proc Address_Insert {} { global aliases address alias if {[string length $alias] > 0} { set exists [info exists aliases($alias)] AliasesDirty lappend aliases($alias) $address if {! $exists} { Aliases_Rebuild $alias } Address_Rebuild $address } } # # Address_Change: # # Change the current address. # proc Address_Change {} { global aliases address alias set current [.aliaspref.addr.listbox curselection] if {([llength $current] == 1) && ([string length $alias] > 0) && ([string length $address] > 0)} { set oldaddr [.aliaspref.addr.listbox get $current] if ![info exists aliases($alias)] { AliasesDirty set aliases($alias) $address Aliases_Rebuild $alias Address_Rebuild $address } else { set pos [lsearch $aliases($alias) $oldaddr] if {$pos >= 0} { AliasesDirty set aliases($alias) \ [lreplace $aliases($alias) $pos $pos $address] Address_Rebuild $address } } } } # # Address_Delete: # # Delete the current selection from the list of addresses # proc Address_Delete {} { global aliases alias address if {([string length $address] > 0) && ([string length $alias] > 0) && [info exists aliases($alias)]} { set pos [lsearch $aliases($alias) $address] if {$pos >= 0} { set aliases($alias) \ [lreplace $aliases($alias) $pos $pos] AliasesDirty Address_Rebuild } } } # # AliasesDismiss: # # See if the database has been modified before quiting. # proc AliasesDirty {} { global aliasesDirty set aliasesDirty 1 } proc AliasesIsDirty {} { global aliasesDirty if ![info exists aliasesDirty] { return 0 } else { return $aliasesDirty } } proc AliasesClean {} { global aliasesDirty set aliasesDirty 0 } proc AliasesIsClean {} { global aliasesDirty return [expr ! $aliasesDirty] } proc AliasesDismiss {} { set ok 0 if [AliasesIsDirty] { if [AliasesDirtyDialog] { set ok 1 } } else { set ok 1 } if {$ok} { catch {destroy .aliashelp} Exwin_Dismiss .aliaspref } } proc AliasesDirtyDialog {} { if [catch {frame .aliaspref.dirty -bd 4 -relief ridge} t] { Aliases_Save destroy .aliaspref.dirty return 1 } message $t.msg -aspect 1000 -text "Save changes to aliases?" pack $t.msg -padx 20 -pady 20 FontWidget button $t.yes -text OK -command { Aliases_Save destroy .aliaspref.dirty } FontWidget button $t.no -text Cancel -command { destroy .aliaspref.dirty } FontWidget button $t.reset -text Reset -command { Aliases_Load Aliases_Rebuild Exmh_Status "Reset aliases" destroy .aliaspref.dirty } pack $t.yes $t.no $t.reset -padx 20 -side right Widget_PlaceDialog .aliaspref .aliaspref.dirty tkwait window .aliaspref.dirty return [AliasesIsClean] } proc Aliases_CheckPoint {} { if [AliasesIsDirty] { Aliases_Save } } # # Aliases_Load: # # This procedure attempts to load the MH alias file indicated in the # MH profile, creating it if necessary. The contents of the alias # file will be stored in the global aliases array. # proc Aliases_Load {} { global aliases mhProfile aliasesOrder aliases_sep AliasesClean catch {unset aliases} ; set aliases(foo) foo ; unset aliases(foo) set aliasesOrder {} if ![info exists mhProfile(aliasfile)] { return } if [catch {open [Mh_Pathname $mhProfile(aliasfile)]} input] { Exmh_Status "Cannot open [Mh_Pathname $mhProfile(aliasfile)]: $input" return } # clear the old aliases array and load the new one set continue 0 while {[gets $input line] >= 0} { set cont $continue if [regexp {\\$} $line] { set continue 1 set line [string trimright $line \\] } else { set continue 0 } if {$cont} { # append aliases($key) $line regsub -all {[ ]*,[ ]*} $line , value set aliases($key) \ [concat $aliases($key) [split [string trim $value "\t ,"] ,]] } else { if [regexp {^[ ]*[;#:]} $line] { lappend aliasesOrder $line } elseif [regexp "^\[ \t\]*$" $line] { lappend aliasesOrder $line } elseif [regexp "^\[ \t\]*<" $line] { lappend aliasesOrder $line } else { regexp {([^;:]+)([:;])(.*)} $line match key sep other lappend aliasesOrder [string trim $key] # set aliases($key) $other regsub -all {[ ]*,[ ]*} $other , value set aliases($key) [split [string trim $value "\t ,"] ,] set aliases_sep($key) $sep } } } # foreach key [array names aliases] { # set aliases($key) [AliasesChop $aliases($key)] # } close $input } proc AliasesChop { rawline } { # Doomed to failure. set list {} Exmh_Debug AliasesChop $rawline while {[string length $rawline] > 0} { if [regexp -indices {^[ ]*("[^"]+"[ ]*<[^>]+>)[ ]*,?} \ $rawline match addr] { Exmh_Debug "AliasesChop regexp1" [eval {string range $rawline} $addr] lappend list [eval {string range $rawline} $addr] set next [expr [lindex $match 1]+1] set rawline [string range $rawline $next end] } elseif [regexp -indices {^[ ]*(\([^\)]+\)[ ]*<[^>]+>)[ ]*,?}\ $rawline match addr] { Exmh_Debug "AliasesChop regexp2" [eval {string range $rawline} $addr] lappend list [eval {string range $rawline} $addr] set next [expr [lindex $match 1]+1] set rawline [string range $rawline $next end] } elseif [regexp -indices {^[ ]*(<[^>]+>)[ ]*,?}\ $rawline match addr] { Exmh_Debug "AliasesChop regexp3" [eval {string range $rawline} $addr] lappend list [eval {string range $rawline} $addr] set next [expr [lindex $match 1]+1] set rawline [string range $rawline $next end] } elseif [regexp -indices {^[ ]*([^ ]+)[ ]*,?}\ $rawline match addr] { Exmh_Debug "AliasesChop regexp4" [eval {string range $rawline} $addr] lappend list [eval {string range $rawline} $addr] set next [expr [lindex $match 1]+1] set rawline [string range $rawline $next end] } else { Exmh_Debug "AliasesChop miss" break } } } # # Aliases_Save: # # This procedure writes the contents of the aliases array to the MH # alias file indicated in the MH profile. # proc Aliases_Save {} { global aliases mhProfile aliasesOrder aliases_sep if [info exists aliases] { if [catch {open [Mh_Pathname $mhProfile(aliasfile)] w} output] { puts stderr "Cannot write [Mh_Pathname $mhProfile(aliasfile)]: $output" return } foreach alias $aliasesOrder { if [regexp {^[ ]*[;#]} $alias] { puts $output $alias } elseif [regexp {^[ ]*$} $alias] { puts $output $alias } elseif [regexp {^[ ]*<} $alias] { puts $output $alias } elseif [info exists aliases($alias)] { if [catch {set aliases_sep($alias)} sep] { set sep : } puts -nonewline $output "$alias$sep " set col [string length "$alias: "] set first 1 foreach a $aliases($alias) { if {! $first} { puts -nonewline $output ", " incr col 2 } else { set first 0 } set l [string length $a] if {($col + $l > 77)} { puts $output \\ puts -nonewline $output \t set col 8 } puts -nonewline $output $a incr col $l } puts $output "" } } close $output AliasesClean Exmh_Status "Saved aliases" } } proc Aliases_Import {} { global mhProfile if [AliasesIsDirty] { if ![AliasesDirtyDialog] { return } } if ![info exists mhProfile(aliasfile)] { if ![AliasesInitProfile] { return } } set f [frame .aliaspref.import -bd 4 -relief ridge] Widget_Message $f msg -aspect 1000 -text " Exmh knows how to import aliases from .mailrc-like files. The format it expects is alias Foo Bar@xyz Enter the file name and hit OK" Widget_Frame $f rim Pad {top expand fill} $f.rim configure -bd 10 Widget_Label $f.rim l {left} -text "mailrc file name: " Widget_Entry $f.rim e {left fill} -width 30 $f.rim.e insert 0 [glob ~]/.mailrc set aliasOK 0 Widget_Frame $f.rim but Menubar {top fill} Widget_AddBut $f.rim.but yes "OK" [list AliasesImportOK $f.rim.e $f] Widget_AddBut $f.rim.but no "Cancel" [list destroy $f] Widget_PlaceDialog .aliaspref $f tkwait window $f } proc AliasesImportOK { entry dialog } { if [Aliases_ImportFile [$entry get]] { Aliases_Load Aliases_Rebuild destroy $dialog } else { lower $dialog update idletasks raise $dialog } } proc Aliases_ImportFile { f } { global mhProfile aliases if [catch {glob $f} file] { Exmh_Status $file return 0 } if ![info exists mhProfile(aliasfile)] { Exmh_Status "No AliasFile MH profile" return 0 } if [catch {exec egrep {^[ ]*alias} $file} new_aliases] { Exmh_Status "No aliases in $file" return 0 } set out [open [Mh_Pathname $mhProfile(aliasfile)] {WRONLY CREAT APPEND}] foreach a [split $new_aliases \n] { if [regexp {^alias ([^ ]+)[ ](.*)$} $a match key value] { regsub -all { +} $value {, } value if ![info exists aliases($key)] { puts $out "$key: $value" } } else { Exmh_Status "Cannot regexp $a" } } close $out return 1 } exmh-2.9.0/lib/faces.tcl0000644000170700017070000003357613201227060014357 0ustar valdisvaldis# # faces.tcl # # facesaver support (bitmap display of who sent a message). # # Copyright (c) 1993 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. #### Faces support set faces(debug) 0 proc Dputs args { global faces; if $faces(debug) {puts $args} } set faces(timing) 0 proc Tputs args { global faces; if $faces(timing) {puts $args} } # Compute faces search path proc Face_SetPath {} { global faces env faceCache catch {unset faceCache} if ![info exists faces(sets)] { if [info exists faces(set)] { # backwards compatibility with old "exmh" script set faces(set,user) $faces(set) set faces(set,unknown) $faces(set) set faces(set,news) $faces(set) } set faces(sets) {user unknown} } # tail component for each set set faces(name,user) {$user} set faces(name,unknown) unknown set faces(name,news) unknown set faces(defaultDomain) [string tolower \ [string trim $faces(defaultDomain) ". "]] # Build search path foreach set $faces(sets) { set faces(path,$set) {} } set faces(path,news) {} if [info exists env(FACEPATH)] { set faces(base) "" foreach dir [split $env(FACEPATH) :] { foreach set $faces(sets) { if ![file isdirectory $dir] continue if {[lsearch -exact $faces(set,$set) [file tail $dir]] >= 0} { FaceAddPath $set $dir } else { FaceAddPath user $dir FaceAddPath unknown $dir FaceAddPath news $dir } } } } else { set faces(base) $faces(dir)/ foreach set $faces(sets) { foreach dir $faces(set,$set) { if ![file isdirectory $faces(base)$dir] continue FaceAddPath $set $dir } } if [info exists faces(set,news)] { foreach dir $faces(set,news) { if ![file isdirectory $faces(base)$dir] continue FaceAddPath news $dir } } } } proc FaceAddPath {set dir} { global faces lappend faces(path,$set) $dir set mmap [file exists $faces(base)$dir/machine.tab] set pmap [file exists $faces(base)$dir/people.tab] set faces(map,$dir) [expr ($mmap<<1) + $pmap] if [file isdirectory $faces(base)$dir/MISC] { lappend faces(path,$set) $dir/MISC set faces(map,$dir/MISC) 0 } } proc Face_Show { fromwho {xface {}} {ximageurl {}} {newsgrps {}} } { global faces faceCache failedURLs exmh set xfaceAvail 0 set ximageurlAvail 0 # Don't do any of this if we're on a slow display if {!$exmh(slowDispShowFaces)} { return 0 } Face_Delete # Honor X-Face even if faces is disabled if {$faces(xFaceEnabled) && \ [string compare "" $xface] && \ [string compare "" $faces(xfaceProg)]} { if {$faces(rowEnabled) && $faces(defer)} { DeferWork faces(work) [list FaceXFace $xface [FaceAlloc]] } elseif {[FaceXFace $xface] && !$faces(rowEnabled)} { set xfaceAvail 1 } } # Honor X-Image-URL even if X-Face was displayed or the faces are # disabled if {$faces(xImageUrl) && [string compare "" $ximageurl]} { if {![info exists failedURLs] || ([info exists failedURLs] && [lsearch $failedURLs $ximageurl] == -1)} { if {$faces(rowEnabled) && $faces(defer)} { DeferWork faces(work) \ [list UrlDisplayFace $ximageurl [FaceAlloc]] } elseif {[UrlDisplayFace $ximageurl [FaceAlloc]] && !$faces(rowEnabled)} { set ximageurlAvail 1 } } } if {$xfaceAvail || $ximageurlAvail} { return 1 } if {$faces(enabled!) || !$faces(enabled)} { return 0 } # Check for cached lookup result if [info exists faceCache($fromwho,$newsgrps)] { if [Face_ShowFace $faceCache($fromwho,$newsgrps)] { return 1 } unset faceCache($fromwho,$newsgrps) Face_Delete } set msg [Exmh_OldStatus] Exmh_Status "Looking up face of $fromwho ..." set parts [string tolower [split $fromwho @]] set user [lindex $parts 0] set machine [lindex $parts 1] if {[string length $machine] == 0} { set machine [string tolower $faces(defaultDomain)] } elseif {[string first . $machine] == -1} { append machine . $faces(defaultDomain) } set from [split $machine .] set pathlist [FacePathlist $from] #Exmh_Debug \n$user ==> $pathlist set pathlistngfull {} if {[string compare "" $newsgrps]} { set newsgrplist [string tolower [split $newsgrps ,]] foreach ng $newsgrplist { set ngparts [split $ng .] set pathlistng [FacePathNGlist $ngparts] set pathlistngfull [concat $pathlistng $pathlistngfull] } } # Loop through Face path #Tputs lookup: [time { set matches {} foreach set $faces(sets) { eval set tail $faces(name,$set) foreach dir $faces(path,$set) { set name $tail set map {} if $faces(map,$dir) { if {$faces(map,$dir) & 2} { set map [FacePathlist [split \ [FaceMap $dir/machine.tab $machine] .]] # Exmh_Debug $machine => $map } if {$faces(map,$dir) & 1} { set x [FaceMap $dir/people.tab $machine/$name] # Exmh_Debug $machine/$name => $x if [string compare "" $x] { set name $x } } } foreach part [concat $map $pathlist] { if {([string match unknown* $dir] || [string match misc* $dir]) && [llength $matches]} { break } set path $dir/$part/$name # Exmh_Debug $path # skip non-existent directories if ![file exists $faces(base)$path] continue foreach suf $faces(suffix) { if [file exists $faces(base)$path/face.$suf] { lappend matches $path/face.$suf break } } } } } # }] eval set tail $faces(name,news) foreach dir $faces(path,news) { set name $tail set map {} foreach part [concat $map $pathlistngfull] { # if {([string match unknown* $dir] || [string match misc* $dir]) # && [llength $matches]} { # break # } set path $dir/$part/$name # Exmh_Debug $path # skip non-existent directories if ![file exists $faces(base)$path] continue foreach suf $faces(suffix) { if [file exists $faces(base)$path/face.$suf] { lappend matches $path/face.$suf break } } } } # Exmh_Debug Faces matches $matches if !$faces(rowEnabled) { foreach face $matches { if [Face_ShowFile $face] { set faceCache($fromwho,$newsgrps) $face Exmh_Status $msg return 1 } } # braces around cmdsubst NECESSARY! } elseif {[Face_ShowFace $matches]} { set faceCache($fromwho,$newsgrps) $matches Exmh_Status $msg return 1 } if [llength $matches] { Exmh_Status "(no working face found)" } else { Exmh_Status "(no face found)" } return 0 } proc FacePathlist { from } { set path {} set prefix {} set pathlist {} for {set i [expr [llength $from]-1]} {$i>=0} {incr i -1} { append path $prefix [lindex $from $i] set prefix / set pathlist [linsert $pathlist 0 $path] } lappend pathlist {} return $pathlist } proc FacePathNGlist { ng } { set path {} set prefix {} set pathlist {} for {set i 0} {$i <= [expr [llength $ng]-1]} {incr i 1} { append path $prefix [lindex $ng $i] set prefix / set pathlist [concat $path $pathlist] } lappend pathlist {} return $pathlist } proc Face_Delete {} { global faces if [info exists faces(work)] { DeferWorkCancel faces(work) } for {set f $faces(avail)} {$f > 0} {incr f -1} { catch { set image [$faces(frame).l$f cget -image] if [string compare "" $image] { $faces(frame).l$f config -image {} image delete $image } } $faces(frame).l$f config -bitmap {} if {$faces(rowEnabled) && [info exists faces(rowbg)]} { $faces(frame).l$f config -bg $faces(rowbg) } } set faces(avail) 0 if !$faces(rowEnabled) { raise $faces(default) } } proc FaceAlloc {} { global faces set new 0 if {!$faces(rowEnabled) && $faces(avail)} { catch { set image [$faces(frame).l$faces(avail) cget -image] if [string compare "" $image] { $faces(frame).l$faces(avail) config -image {} image delete $image } } incr faces(avail) -1 ;# make us alloc same label } if {$faces(avail) == $faces(alloc)} { Widget_Label $faces(frame) l[incr faces(alloc)] {left fill} set new 1 } set label $faces(frame).l[incr faces(avail)] if !$faces(rowEnabled) { if $new { ;# once ever pack forget $label place $label -in $faces(default) } } elseif !$new { $label config -bg $faces(facebg) } return $label } proc Face_BusyParent {} { global faces return $faces(frame) } proc Face_BusyPlace {busy} { global faces place $busy -in $faces(frame) -anchor c -relx 0.5 -rely 0.5 raise $busy update idletasks } proc Face_BusyDestroy {busy} { global faces catch { destroy $busy # This hack forces the underlying labels to redisplay immediatly $faces(default) config -fg [lindex [$faces(default) config -fg] 4] $faces(frame).l1 config -fg [lindex [$faces(frame).l1 config -fg] 4] } } proc Face_ShowFace facelist { foreach face $facelist { if ![FaceShowFile $face [FaceAlloc]] { return 0 } } return 1 } proc Face_ShowFile facefile { set pane [FaceAlloc] if ![FaceShowFile $facefile $pane] { $pane config -bitmap error return 0 } return 1 } proc FaceShowFile {facefile pane} { global faces if ![string match /* $facefile] { set facefile $faces(base)$facefile } switch -- [file extension $facefile] { .ppm - .pgm - .pbm - .gif - .xpm { if [catch { # Tputs image create: [time { set image [image create photo -file $facefile -palette $faces(palette)] # }] if $faces(defer) { DeferWork faces(work) [list $pane config -image $image] \ [list image delete $image] } else { # Tputs image display: [time { $pane config -image $image # }] } } id] { Exmh_Debug FaceShowFile $id return 0 } } .xbm { if [catch { $pane config -bitmap @$facefile } id] { Exmh_Debug FaceShowFile $id return 0 } } } if !$faces(rowEnabled) { raise $pane } return 1 } proc FaceXFace { xface {pane {}}} { global faces Exmh_Status "$faces(xfaceProg)" warning # Tputs decode x-face: [time { if [catch {open "| $faces(xfaceProg) > [Env_Tmp]/FACE.[pid].xbm" w} fid] { Exmh_Status $fid error return 0 } else { Exmh_Status "$faces(xfaceProg)" } puts $fid $xface if [catch {close $fid} err] { Exmh_Status $err error return 0 } # }] if [string match "" $pane] { set pane [FaceAlloc] } # Tputs show x-face: [time { set ret [FaceShowFile [Env_Tmp]/FACE.[pid].xbm $pane] # }] File_Delete [Env_Tmp]/FACE.[pid].xbm Exmh_Status ok return $ret } # # Hook for button in faces area # proc Faces_Button {{cmd ""} {label ""} {pack {left fill}}} { global faces catch {destroy $faces(button)} set faces(button) [Widget_AddBut $faces(frame) b $label $cmd $pack] $faces(button) config -padx 0 -pady 0 pack $faces(button) -after $faces(default) return $faces(button) } proc Faces_ClearButton {} { global faces catch {destroy $faces(button)} } # Faces information used to be administered by a pair of ASCII files # in the faces directory that associate related machines and faces. # EXMH still supports this mechanism, although it's use is discouraged. # The machine table machine.tab attaches machines to communities; the line # stard=sunaus # puts the machine stard in community sunaus. The machine # table may be used to alias entire communities; the line # wseng.sun.com=eng.sun.com # will cause the wseng.sun.com domain to be mapped to the # eng.sun.com community. The people table associates a # community/alias pair, with a real username. # sunaus/rburridge=richb # causes the alias rburridge to be translated into the real # username richb for the community sunaus proc FaceMachine {dir machine} { global faces if $faces(mapsEnabled) { set map [FaceMap $dir/machine.tab $machine] if [string compare "" $map] { return $map } } return $machine } proc FacePeople {dir machine people} { global faces if $faces(mapsEnabled) { set map [FaceMap $dir/people.tab $machine/$people] switch -- [llength $map] { 0 {} 1 {return [list $machine $map]} default {return $map} } } return [list $machine $people] } proc FaceMap {file item} { global faceMap faces if [info exists faceMap($file,$item)] { return $faceMap($file,$item) } if { [info exists faceMap(modtime,$file)] && ([file mtime $faces(base)$file] <= $faceMap(modtime,$file)) } { return {} } # Exmh_Debug FaceMap $file $item if ![catch {open $faces(base)$file} in] { set faceMap(modtime,$file) [file mtime $faces(base)$file] while {[gets $in input] >= 0} { set parts [string tolower [split $input =]] set lhs [string trim [lindex $parts 0]] set rhs [split [string trim [lindex $parts 1]] /] set faceMap($file,$lhs) $rhs } close $in if [info exists faceMap($file,$item)] { return $faceMap($file,$item) } } return {} } proc Face_FlushCache {} { global faceMap faceCache catch {unset faceMap} catch {unset faceCache} } # # Defer work to an after handler [this code should be elsewhere] # proc DeferWork {name work {cancel {}}} { upvar #0 $name queue lappend queue [list $work $cancel] if {[llength $queue] == 1} { after 50 DeferWorkProc $name } } proc DeferWorkCancel name { upvar #0 $name queue if [info exists queue] { after cancel [list DeferWorkProc $name] foreach w $queue { catch [lindex $w 1] } unset queue } } proc DeferWorkProc name { upvar #0 $name queue set this [lindex $queue 0] set queue [lrange $queue 1 end] catch [lindex $this 0] if [llength $queue] { after 20 DeferWorkProc $name } } exmh-2.9.0/lib/bogo.tcl0000644000170700017070000001307213201227060014211 0ustar valdisvaldisproc Bogo_Init {} { global bogo Preferences_Add "Bayesian Spam Filter" \ "Parameters for Bayesian spam filters that have to be told if they marked messages incorrectly. Your usage of this feature will depend on how you call it from procmail. See your program's man page for details." { {bogo(inUse) bogoinUse OFF {Use a Bayesian spam filter} "Enables support for the 'learn' mode for training various popular Bayesian spam filters"} {bogo(progname) bogoProgName {CHOICE bogofilter spamoracle spamassassin other} {Spam Program} "Which spam program you use. If it is not in your $PATH, select other and give the full path name."} {bogo(mismarked) bogoMismarked ON {Is spam mismarked?} "When you run the filter from procmail, does it add the tokens? If it does, then spam that makes it through is mismarked, and you want this flag on. This only matters for bogofilter: On means it uses -Sn and -Ns; for off it uses -s and -n."} {bogo(otherspam) bogoOtherSpam {} {Other--Spam} "How the program is invoked, flags included, for spam."} {bogo(otherham) bogoOtherHam {} {Other--Non-Spam} "How the other program is invoked, flags included, for non-spam."} {bogo(spammessage) bogoSpamMessage {CHOICE nothing rmm refile} {Spam Procedure} "What to do with a spam message after your Bayesian filter has reclassified it."} {bogo(spamfolder) bogoSpamRefile bogus {Spam Folder} "If you selected 'refile' for spam messages, this is the destination folder."} {bogo(hammessage) bogoHamMessage {CHOICE nothing refile} {Ham Procedure} "What to do with a ham message after your Bayesian filter has reclassified it."} {bogo(hamfolder) bogoHamRefile inbox {Ham Folder} "If you selected 'refile' for ham messages, this is the destination folder."} {bogo(stdin) bogoStdin ON {Feed messages on STDIN?} "If your filter expects mails to be passed via STDIN, leave this on. Your program will be passed mails via STDIN, one per invocation. Otherwise your filter program will get a list of files as arguments. Spamassassin supports either method."} } trace variable bogo(progname) w BogoSetup BogoSetup } proc BogoSetup {args} { global bogo case $bogo(progname) { "bogofilter" { if {$bogo(mismarked)} { set bogo(spamprog) {bogofilter -Ns} set bogo(hamprog) {bogofilter -Sn} } else { set bogo(spamprog) {bogofilter -s} set bogo(hamprog) {bogofilter -n} } } "spamoracle" { set bogo(spamprog) {spamoracle add -good} set bogo(hamprog) {spamoracle add -spam} } "spamassassin" { set bogo(spamprog) {sa-learn --spam} set bogo(hamprog) {sa-learn --ham} } "other" { set bogo(spamprog) $bogo(otherspam) set bogo(hamprog) $bogo(otherham) } } } proc Bogo_Filter {{spam spam}} { global exmh msg bogo mhProfile Exmh_Debug Bogo $spam if {!$bogo(inUse)} { Exmh_Status "Bayesian filter not enabled in Preferences" return } if {$spam == "spam"} { set msgs [Ftoc_CurMsgs] Exmh_Status "Marking [llength $msgs] msg[expr {[llength $msgs] > 1 ? "s" : ""}] as SPAM" Exmh_Debug Bogo spamprog="$bogo(spamprog)", message="$msgs", action="$bogo(spammessage)" if {$bogo(stdin)} { Ftoc_MsgIterate msgid { if [catch "exec $bogo(spamprog) <$mhProfile(path)/$exmh(folder)/$msgid" in] { Exmh_Status $in return } } } else { set paths {} Ftoc_MsgIterate msgid { lappend paths "$mhProfile(path)/$exmh(folder)/$msgid" } if [catch "exec $bogo(spamprog) $paths" in] { Exmh_Status $in return } } if {$bogo(spammessage) == "rmm"} { Msg_Remove Ftoc_RemoveMark show } if {$bogo(spammessage) == "refile"} { set oldtarget $exmh(target) set exmh(target) $bogo(spamfolder) Exmh_Debug Bogo refile spam to $exmh(target) Msg_Move Ftoc_MoveMark 1 noshow set exmh(target) $oldtarget } return } elseif {$spam == "ham"} { set msgs [Ftoc_CurMsgs] Exmh_Status "Marking [llength $msgs] msg[expr {[llength $msgs] > 1 ? "s" : ""}] as HAM" Exmh_Debug Bogo hamprog="$bogo(hamprog)", message="$msgs", action="$bogo(hammessage)" if {$bogo(stdin)} { Ftoc_MsgIterate msgid { if [catch "exec $bogo(hamprog) <$mhProfile(path)/$exmh(folder)/$msgid" in] { Exmh_Status $in return } } } else { set paths {} Ftoc_MsgIterate msgid { lappend paths "$mhProfile(path)/$exmh(folder)/$msgid" } if [catch "exec $bogo(hamprog) $paths" in] { Exmh_Status $in return } } if {$bogo(hammessage) == "refile"} { set oldtarget $exmh(target) set exmh(target) $bogo(hamfolder) Exmh_Debug Bogo refile ham to $exmh(target) Msg_Move Ftoc_MoveMark 1 noshow set exmh(target) $oldtarget } return } else { Exmh_Status "Spam button config error." return } } proc Bogo_FilterFolder {{spam spam}} { global exmh bogo global mhProfile set folder $exmh(folder) if {!$bogo(inUse)} { Exmh_Status "Bayesian filter not enabled in Preferences" return } Exmh_Status "Learning $exmh(folder) as $spam" if {$bogo(progname) != "spamassassin"} { Exmh_Status "Only sa-learn is currently supported for learning a folder" return } set pipe [open "|sa-learn --$spam $mhProfile(path)/$exmh(folder)"] fileevent $pipe readable [list BogoFilterReader $pipe $exmh(folder) $spam] } proc BogoFilterReader {pipe folder spam} { if {[eof $pipe]} { Exmh_Status "Learned $folder as $spam" if {[catch {close $pipe} err]} { Exmh_Debug "sa-learn $folder: $err" } } else { gets $pipe line Exmh_Debug "BogoFilterReader: $line" } } exmh-2.9.0/lib/background.tcl0000644000170700017070000003156013201227060015404 0ustar valdisvaldis# # exmh_background.tcl -- # Periodic background processing # # Copyright (c) 1993 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. # Background processing proc Background_Init {} { global exmh env background if ![info exists env(MAIL)] { set spool /usr/spool/mail/$env(USER) } else { set spool $env(MAIL) } Preferences_Add "Background Processing" \ "A second process is used to perform various background tasks for Exmh. These options control its behavior." \ [list \ { exmh(bgAsync) bgAsync ON {Separate background process} "This setting determines whether or not the background processing is done in a separate process or not. A separate process causes less interference with the user interface, but might take up more machine resources."} \ { exmh(sendHack) sendHack ON {Keep xhost list clear} "The Tk send command will stop working if hosts are added to your xhost list, even if you are using Xauthority. This option replaces the send command with a version that clears out the xhost list if hosts are found on it."} \ { exmh(background) bgAction {CHOICE off count msgchk flist inc hook} {Background processing} "exmh can periodically do some things for you: count - count new messages sitting in your spool file. msgchk - run the MH msgchk program. flist - check for new mail in all folders. inc - just like clicking the Inc button yourself. hook - suppply your own Hook_Background procedure. off - do nothing in the background."} \ { exmh(bgPeriod) bgPeriod 10 {Period (minutes)} "How often to do background task"} \ {exmh(bgNews) bgNews OFF {Background News Retrieval} "Retrieve News via NNTP in the background. See the Preferences for NNTP support for more information"} \ { exmh(bgNewsPeriod) bgNewsPeriod 60 {Period (minutes)} "How often to do background News Retrieval"} \ [list exmh(spool) bgSpool $spool {Mail spool pathname} \ "Pathname for the mail spool file that gets new messages."] \ ] # due to a TK bug I cannot trace the radio button variable directly. # I can hack around it by tracing the bgPeriod, which is always # set by Preferences because it is an entry trace variable exmh(bgPeriod) w BackgroundFixup if {$exmh(bgPeriod) <= 0} { set exmh(bgPeriod) 10 } set exmh(lastBackground) $exmh(background) set exmh(timeSinceBgNews) -1 if {0} { if [catch {User_Layout} err] { puts stderr "User_Layout: $err" } } set background(lastMsgChk) {} set exmh(sendErrors) 0 if {$exmh(sendHack)} { source $exmh(library)/send.tcl } } proc Background_Startup {} { global exmh inc if [info exists exmh(interp)] { # Already in the background interpreter. # Invoked because the style of background processing changed Background_DoPeriodic return } if [info exists exmh(bgInterp)] { if {[catch {send $exmh(bgInterp) {Background_Startup}}] == 0} { # Background interp already running return } } Background_Cleanup ;# In case the bg process is really there anyway if {! $exmh(bgAsync) } { # Do not run a separate process Background_DoPeriodic return } global mh_path argv0 wish set prog ${argv0}-bg Exmh_Status "Starting: $prog" set cmd [list exec $wish -f $prog [winfo name .] $exmh(library) $mh_path &] if [catch { set pid [eval $cmd] set exmh(bgPid) $pid Exmh_Debug Background_Startup $exmh(background) pid $pid after [expr 10*1000*60] BackgroundCheckup } err] { Exmh_Status "exmh-bg error: $err" Background_DoPeriodic } } proc BackgroundCheckup {} { global exmh Exmh_Debug BackgroundCheckup if [BgLostPid $exmh(bgPid) exmh-bg] { catch {unset exmh(bgInterp)} Exmh_Debug Restarting exmh-bg Background_Startup } else { after [expr 10*1000*60] BackgroundCheckup } } proc Background_Register { bgInterp {bgPid junk} } { # Invoked by the background interpreter so we can talk back to it global exmh set exmh(bgInterp) $bgInterp if {$bgPid != "junk"} { set exmh(bgPid) $bgPid } Exmh_Debug "Background interp is $bgInterp, pid $exmh(bgPid)" # Bundle up some parameters that could be overridden on the # command line and so won't get picked up from the Xresources set exmh(pid) [pid] ;# TCL 7.* dependent foreach varname {exmh(background) exmh(bgPeriod) exmh(pid)} { lappend results [list $varname [set $varname]] } return $results } proc Background_Cleanup {} { global exmh bgaction if [catch {send $exmh(bgInterp) Exmhbg_Done [winfo name .]}] { catch {exec kill $exmh(bgPid)} } catch { foreach action [array names bgaction] { BackgroundComplete $action } } foreach interp [winfo interps] { if {[string match $exmh(name)-bg* $interp]} { catch {send $interp Exmhbg_Done [winfo name .]} } } } proc Background_DoPeriodic {} { global exmh Exmh_Debug Background_DoPeriodic $exmh(background) switch -- $exmh(background) { "count" { set bgProc BackgroundCount } "msgchk" { set bgProc BackgroundMsgChk } "inc" { set bgProc BackgroundInc } "flist" { set bgProc BackgroundFlist } "hook" { set bgProc [info commands Hook_Background] if {[string length $bgProc] == 0} { Exmh_Status "Hook_Background undefined (hook background option)" set exmh(background) off } } default { set bgProc {} } } if {[string length $bgProc] != 0} { if [catch $bgProc err] { Exmh_Debug "DoPeriodic" $bgProc $err } } if {$exmh(bgNews)} { if {(($exmh(timeSinceBgNews) == -1) || ($exmh(timeSinceBgNews) > ($exmh(bgNewsPeriod) * 60)))} { GetNews set exmh(timeSinceBgNews) 0 } incr exmh(timeSinceBgNews) [expr int($exmh(bgPeriod) * 60)] } after [expr int($exmh(bgPeriod)*1000*60)] Background_DoPeriodic } proc Background_Off {} { global exmh set exmh(background) {} } proc BackgroundFixup { args } { global exmh Exmh_Debug BackgroundFixup $exmh(lastBackground) $exmh(background) if {[catch {expr $exmh(bgPeriod)*1000*60}] || ($exmh(bgPeriod) <= 0)} { set exmh(bgPeriod) 10 } if {$exmh(background) != $exmh(lastBackground)} { Background_Startup set exmh(lastBackground) $exmh(background) } } proc BackgroundMsgChk {} { global exmh env background set result [Mh_MsgChk] if {$result != $background(lastMsgChk)} { BgRPC BackgroundMsgChkInner $result Exmh_Status $result set background(lastMsgChk) $result } } proc BackgroundMsgChkInner {result} { global background exmh Exmh_Status $result set background(lastMsgChk) $result switch -glob -- $result { "You have*" {set exmh(numUnInced) "Some"; Flag_Spooled} "You don't*" {set exmh(numUnInced) 0; Flag_NoSpooled} } } proc BackgroundCount {} { global exmh env if ![catch {Mh_MsgCount $exmh(spool)} newmsgs] { BgRPC BackgroundNewMsgs [string trim $newmsgs] } } proc BackgroundNewMsgs { N } { global exmh if ![info exists exmh(numUnInced)] { set exmh(numUnInced) 0 } if {$N > 0} { if {$N == 1} { set msg "msg" } else { set msg "msgs" } set exmh(numUnInced) $N Exmh_Status "You have $N spooled $msg" Flag_Spooled } else { Flag_NoSpooled if {$exmh(numUnInced) > 0} { Exmh_Status "" } set exmh(numUnInced) $N } } proc BackgroundInc {} { Inc } proc BackgroundFlist {} { Flist_FindSeqs ;# Update folder highlights BgRPC Inc_PresortFinish ;# Update scan listing } # Invoke something in the background interpreter, if it exists proc BgAction { tag args } { global exmh Exmh_Debug BgAction $tag $args Audit "$tag $args" if [info exists exmh(bgInterp)] { BackgroundPending $tag ;# Register outstanding request if ![catch { send $exmh(bgInterp) [list after 1 [list BgProcess $tag $args]] } err] { return } BackgroundComplete $tag Exmh_Debug BgAction $err } eval $args foreach cmd [info commands Hook_Bg$tag*] { $cmd } } # Run something in the background and report back to the front end proc BgProcess { tag cmd } { global exmh if [catch $cmd err] { Exmh_Status $err } if [catch {send $exmh(interp) [list BackgroundComplete $tag]} err ] { catch {puts stderr "exmh-bg: BackgroundComplete($tag) failed: $err"} Exmh_Status $err } } # Invoke a routine in the UI interpreter, if it exists, else ourselves. # If there is no separate background process, then # exmh(interp) does not exist, and we just eval the command # in the current process, which is already the UI. proc BgRPC { args } { global exmh if [info exists exmh(dead)] { return } set check [info exists exmh(pid)] if [info exists exmh(interp)] { # Send command to main, front-end interpreter set fail {} # if {$check && [BgLostPid $exmh(pid) exmh]} { # # Front-end died or may have restarted - bail out # set fail "process $exmh(pid)" # } else { if [catch {send $exmh(interp) $args} err] { switch -- $err { {remote\ interpreter\ did\ not\ respond} { if {$check && [BgLostPid $exmh(pid) exmh]} { set fail "process $exmh(pid)" } } {no\ registered\ interpeter*} { set fail "interp $exmh(interp)" } {no\ application\ named*} { set fail "interp $exmh(interp)" } default { catch {puts stderr "exmh-bg: send error from command \"$args\", error \"$err\""} #puts stderr "BgRPC: $args: $err" } } } else { return $err } # } if {"$fail" != ""} { unset exmh(interp) catch {puts stderr "exmh-bg: lost UI $fail"} exit } } else { # Eval in main, front-end interpreter uplevel #0 $args } } proc BgLostPid { pid {name notused} } { global exmh ps if [catch {PsByID $pid} err] { catch {puts stderr "BgLostPid $ps(cmd) $ps(pflag) $pid: $err"} return 1 } else { foreach line [split $err \n] { if {[string compare [lindex $line 0] $pid] == 0} { return 0 } } catch {puts stderr "BgLostPid pid $pid: cannot find in ps output"} return 1 } } proc BgLostPidOld { pid {name notused} } { if [catch {exec ps $pid} err] { if [string match {[Uu]sage:*} $err] { return [catch {exec ps -p $pid}] } else { return 1 } } else { foreach line [split $err \n] { if {[string compare [lindex $line 0] $pid] == 0} { return 0 } } return 1 } } # Improved version of BgLostPid thanks to Scott Hammond if {0} { set ps ps set ps_opt "" proc BgLostPidClever { pid {name notused} } { global ps ps_opt if [catch "exec $ps $ps_opt $pid" err] { #puts stderr "ps error: $err" if [string match {[Uu]sage:*} $err] { # got usage, so ps must be right, -p should also be right set ps_opt "-p" return [catch {exec $ps -p $pid}] } elseif [string match {*can't find controlling terminal} $err] { if {"$ps" == "ps"} { set ps "/bin/ps" } elseif {"$ps" == "/bin/ps"} { set ps "/usr/ucb/ps" } else { return 1 } return [BgLostPid $pid $name] } else { return 1 } } else { foreach line [split $err \n] { if {[string compare [lindex $line 0] $pid] == 0} { return 0 } } return 1 } } } proc Background_Preferences {} { # Tell the background interpreter to update its per-user settings global exmh if [info exists exmh(bgInterp)] { catch {send $exmh(bgInterp) [list Preferences_Reset]} } } proc BackgroundPending { action } { global bgaction set bgaction($action) 1 Exmh_Debug BackgroundPending $action } proc BackgroundComplete { action } { global bgaction catch {unset bgaction($action)} Exmh_Debug BackgroundComplete $action if [regexp {Refile (.*)} $action x folder] { global exmh if {[string compare $exmh(folder) $folder] == 0} { Exmh_Status "Updating scan listing" Scan_FolderUpdate $folder } } if {[Background_Outstanding] == {}} { Exmh_Status "background actions complete" } foreach cmd [info commands Hook_Bg$action*] { $cmd } } proc Background_Outstanding {} { global bgaction background if [catch {array names bgaction} actions] { set actions {} } if {$actions == {}} { set background(complete) 1 catch {destroy .ftoc.t.abort} } return $actions } proc Background_Wait {} { global background set background(complete) 0 set pending [Background_Outstanding] if {$pending != {}} { Exmh_Status "waiting... $pending" catch { button .ftoc.t.abort -text "Don't Wait" -command Background_Reset place .ftoc.t.abort -relx .5 -rely .5 -anchor c } tkwait variable background(complete) catch {destroy .ftoc.t.abort} } } proc Background_Reset {} { global bgaction foreach act [array names bgaction] { Exmh_Status "Clearing $act" } unset bgaction Background_Outstanding } exmh-2.9.0/lib/pgpGpg.tcl0000644000170700017070000004545613201227060014522 0ustar valdisvaldis# pgpGpg.tcl # $Log$ # Revision 1.18 2017/04/22 01:14:14 sysphrog # Fix gnupg Comment field to dynamically update to the currently running version # # Revision 1.17 2017/03/25 03:02:30 az143 # Summary: small patch in pgpGPG to support long and short keyids # # Revision 1.16 2012/01/22 22:54:45 az143 # az@debian.org repaired gpg cipher option handling # # Revision 1.15 2008/06/18 10:06:15 az143 # patch from debian: added support for gnupg's gpg-agent # # Revision 1.14 2005/01/01 20:16:20 welch # Based on patches from Alexander Zangerl # lib/pgpGpg.tcl: # lib/pgpPgp5.tcl: # fix of an old pgp problem where recipients were duplicated when # pgp is run in interactive mode # lib/extrasInit.tcl: a small documentation improvement for the # pgp(getextcmd) functionality. # faces(xfaceProg) gains a default (uncompface -X) # lib/pgpExec.tcl: fix for http://bugs.debian.org/164210: multiple gpg # subkeys and passphrases. exmh would not ask for the right passphrase. # lib/addr.tcl: ldap options gain defaults that are compatible with # debian's openldap config # lib/mh.tcl: add Msg-Protect and Folder-Protect to the default .mh_profile # that is generated when setting up new users. # # (These changes are inspired by a patch from Alexander, but not the same) # lib/inc.tcl: use $install(dir,bin) to specify an absolute path to # the inc.expect script # lib/seditExtras.tcl: use $install(dir,bin) to specify an absolute path to # the exmh-async script # lib/mime.tcl: use $install(dir,bin) to specify an absolute path to # the ftp.expect script. # Also changed MimeMakeBoundary to use [clock seconds] instead of # re-writing the output of [exec date]. # # Revision 1.13 2001/12/06 16:39:13 kchrist # Exmh can now parse the GnuPG options file and identify the # "default-key" (same as "myname" in PGP). Added "--status-fd 2" to # args_decrypt so that the output can be parsed with Pgp_InterpretOutput. # # Revision 1.12 2000/06/15 17:03:11 valdis # Add X-Mailer: change, fix PGP Comment: line... # # Revision 1.11 2000/04/18 18:38:33 valdis # Fix quote character to use ascii rather than iso8859-ish one # # Revision 1.10 2000/02/07 13:23:34 gruber # fixed run twice function to work with now short keyids # # Revision 1.9 1999/10/25 15:38:39 kchrist # Added a dropKeys pattern to pgpGPG.tcl. # # Simplified PGP GUI by removing "detached" signature option. Problem # was that MIME+standard includes a copy of the message being signed # in the signature attachement. What really should be used is # MIME+detached. Decided to overload the meaning of "standard". If # the format is plain, standard means "binary". If the format is # anything else, standard means "detached". Less flexibility but # better chances of "doing the right thing". # # Revision 1.8 1999/09/30 03:51:07 kchrist # pgp($v,cmd_Beauty) was getting in the way of pgp($v,cmd_User) for # v=gpg so I had to rearrange things a bit. # # Revision 1.7 1999/09/27 23:18:45 kchrist # More PGP changes. Consolidated passphrase entry to sedit field or # pgpExec routine. Made the pgp-sedit field aware of pgp(keeppass) # and pgp(echopass). Moved pgp(keeppass), pgp(echopass) and # pgp(grabfocus) to PGP General Interface. Fixed a minor bug left # over from my previous GUI changes. Made pgp-sedit field appear and # disappear based on its enable preference setting. # # Revision 1.6 1999/08/24 15:51:07 bmah # Patch from Kevin Christian to make email PGP key queries work, and # to make key attachment RFC 2015 compliant. # # Revision 1.5 1999/08/13 15:10:06 bmah # One more try at fixing the problems with 8-byte GPG keyIDs, with a # patch from Kevin.Christian@lsil.com. # # Revision 1.4 1999/08/13 00:39:05 bmah # Fix a number of key/passphrase management problems: pgpsedit now # manages PGP versions, keys, and passphrases on a per-window # basis. Decryption now works when no passphrases are cached. # One timeout parameter controls passphrases for all PGP # versions. seditpgp UI slightly modified. # # Revision 1.3 1999/08/11 04:09:20 bmah # Fix problems caused by GPG returning key IDs that are 8 bytes long, # when exmh (and keyservers) like to work with 4-byte key IDs. # # Revision 1.2 1999/08/03 04:05:54 bmah # Merge support for PGP2/PGP5/GPG from multipgp branch. # # Revision 1.1.4.1 1999/06/14 20:05:15 gruber # updated multipgp interface # # Revision 1.1 1999/06/14 15:14:53 markus # added files # # Revision 1.4 1998/12/14 19:22:42 markus # modulepath, untrusted problem, toplevel # # Revision 1.3 1998/12/07 16:10:20 markus # fixed compressalgo handling # # Revision 1.2 1998/12/06 16:23:44 markus # DecryptExpect and subkey support # # Revision 1.1.1.1 1998/11/24 22:34:46 markus # Initial revision # ####################################################################### # GNUPG CONFIG proc Pgp_gpg_Init {} { global pgp ### # Yes, we need network keyfetching Pgp_WWW_Init set pgp(pref,HKPkeyserverUrl) { HKPkeyserverUrl HKPKeyServerUrl {keys.pgp.com} {Horowitz Key Protocol Server} "The hkp (Horowitz Key Protokol) is a subset of the http. It's used to tranfer keys to and from a keyserver. Give here a hkp server name." } # Needed for Preferences set pgp(gpg,description) "GNUPG is a free GPLed PGP clone written by Werner Koch" set pgp(gpg,prefs) [list rfc822 \ choosekey runtwice cacheids minmatch showinline \ shortmsgs autoextract \ keyserver keyquerymethod HKPkeyserverUrl keyserverUrl \ keyothermethod ] # this is called when preferences are set proc Pgp_gpg_Preferences {} { global exmh pgp # GnuPG algorithms and algorithm modules set label $pgp(gpg,fullName) Preferences_Add "$label interface" {} [list \ [list pgp(gpg,useagent) gpgUseAgent OFF "Use GnuPG Agent" \ "If this option is enabled, then Exmh defers all passphrase handling to GnuPG's gpg-agent. This option overrides and disables the pgpKeepPass option." ] \ [list pgp(gpg,comment) gpgComment \ "Exmh [eval set exmh(version)]" "GnuPG Comment" \ "Specify the comment GnuPG should put in the comment field of encrypted or signed text."] \ [list pgp(gpg,modulepath) gpgModulePath \ {/usr/local/lib/gnupg} "GnuPG Modules Path" \ "GnuPG is able to dynamically load cipher, digest, pubkey etc. algorithm extension modules. Specify a colon (:) separated list of directories, where exmh should look for extension modules."] \ [list pgp(gpg,ciphermods) gpgCipherMods \ {skipjack idea} "GnuPG Cipher Modules" \ "The Cipher Algorithm modules, exmh should look for in the Modules Path."] \ [list pgp(gpg,digestmods) gpgDigestMods \ {tiger} "GnuPG Digest Modules" \ "The Digest Algorithm modules, exmh should look for in the Modules Path."] \ [list pgp(gpg,pubkeymods) gpgPubkeyMods \ {rsa} "GnuPG PubKey Modules" \ "The Public Key Algorithm modules, exmh should look for in the Modules Path."] \ [list pgp(gpg,pgp5compatibility) gpgPgp5Compatibility \ ON "PGP 5.0 Compatibility" \ "You MUST have enabled this if you want that GnuPG produces PGP 5.0 compatible messages. Having this enabled, you don't need PGP 5.0 any more." ] ] ### clear keeppass if agent is on if {[set pgp(gpg,useagent)]} { set pgp(keeppass) 0 } # Before we can build the algorithm choice preferences part # we need to examine, which modules are installed on the system # and build a complete list of algos Pgp_Gpg_Algorithms # preferences Preferences_Add "$label interface" {} [list \ [list pgp(gpg,cipheralgo) gpgCipherAlgo \ [concat CHOICE $pgp(gpg,cipheralgos)] "Default Cipher Algo" \ "Your preferred cipher algorithm. Select 'default' to leave the choice to GnuPG."] \ [list pgp(gpg,digestalgo) gpgDigestAlgo \ [concat CHOICE $pgp(gpg,digestalgos)] "Default Digest Algo" \ "Your preferred digest algorithm. Select 'default' to leave the choice to GnuPG."] \ [list pgp(gpg,compressalgo) gpgCompressAlgo \ [concat CHOICE $pgp(gpg,compressalgos)] "Default Compress Algo" \ "The algorithm, GnuPG uses to compress the text before encrypting. Select 'default' to leave the choice to GnuPG, or 'none' to leave text uncompressed." ] ] } ####################################################################### # GPG BASIC CONFIG # builtin gpg algos set pgp(gpg,cipheralgos) {default cast5 idea 3des blowfish aes aes192 aes256 twofish camellia128 camellia192 camellia256} set pgp(gpg,digestalgos) {default md5 sha1 ripemd160 sha224 sha256 sha384 sha512} set pgp(gpg,compressalgos) {default zip zlib bzip2 none} set pgp(gpg,pubkeyalgos) {} # module files set pgp(gpg,ciphermodfiles) {} set pgp(gpg,digestmodfiles) {} set pgp(gpg,pubkeymodfiles) {} ####################################################################### # Searches Algorithms proc Pgp_Gpg_Algorithms {} { global pgp set wd [pwd] foreach path [split $pgp(gpg,modulepath) :] { set path [string trim $path] catch { cd $path foreach file [glob -nocomplain *] { if { ![file isdirectory $file] } { if {[lsearch $pgp(gpg,ciphermods) $file] >= 0} { lappend pgp(gpg,cipheralgos) $file lappend pgp(gpg,ciphermodfiles) ${path}/$file } elseif {[lsearch $pgp(gpg,digestmods) $file] >= 0} { lappend pgp(gpg,digestalgos) $file lappend pgp(gpg,digestmodfiles) ${path}/$file } elseif {[lsearch $pgp(gpg,pubkeymods) $file] >= 0} { lappend pgp(gpg,pubkeyalgos) $file lappend pgp(gpg,pubkeymodfiles) ${path}/$file } } } } } cd $wd } # Simple Dialog Box to choose Algorithms proc Pgp_gpg_ChooseAlgos {} { global pgp if [winfo exists .gregor] { return } set t [toplevel .gregor] wm title $t "Default Algorithms" wm resizable $t 0 0 set m1 [frame $t.main1] pack $m1 -side left set m2 [frame $t.main2] pack $m2 -side left # Cipheralgo set f [frame $m2.frame1] pack $f -side top -expand 1 -fill x set l [label $m1.cipher -text "Default cipheralgo"] pack $l -side top foreach algo $pgp(gpg,cipheralgos) { set r [radiobutton $f.$algo -variable pgp(gpg,cipheralgo) \ -text $algo -value $algo] pack $r -side left } # Digestalgo set f [frame $m2.frame2] pack $f -side top -expand 1 -fill x set l [label $m1.digest -text "Default digestalgo"] pack $l -side top foreach algo $pgp(gpg,digestalgos) { set r [radiobutton $f.$algo -variable pgp(gpg,digestalgo) \ -text $algo -value $algo] pack $r -side left } # Compressalgo set f [frame $m2.frame3] pack $f -side top -expand 1 -fill x set l [label $m1.compress -text "Default compressalgo"] pack $l -side top foreach algo $pgp(gpg,compressalgos) { set r [radiobutton $f.$algo -variable pgp(gpg,compressalgo) \ -text $algo -value $algo] pack $r -side left } # OK set b [button $f.ok -text "OK" -command "destroy $t"] pack $b -side right } # Forms the standard flags and arguments of the commandline proc Pgp_Gpg_Arglist {} { global pgp set modfiles \ [concat $pgp(gpg,ciphermodfiles) \ $pgp(gpg,digestmodfiles) \ $pgp(gpg,pubkeymodfiles) ] ldelete modfiles {} set arglist [list --no-greeting --comment $pgp(gpg,comment)] if {$pgp(gpg,useagent)} { lappend arglist --use-agent } # Take it if {$pgp(gpg,pgp5compatibility)} { lappend arglist --force-v3-sigs # default: cast5 switch $pgp(gpg,cipheralgo) { 3des {} cast5 {} idea {} default {set pgp(gpg,cipheralgo) cast5} } # default: sha1 switch $pgp(gpg,digestalgo) { md5 {} sha1 {} default {set pgp(gpg,digestalgo) sha1} } switch $pgp(gpg,compressalgo) { zip {} default {set pgp(gpg,compressalgo) zip} } } foreach modfile $modfiles { set arglist [concat $arglist [list \ --load-extension $modfile] ] } if {$pgp(gpg,cipheralgo) != "default"} { lappend arglist --personal-cipher-preferences $pgp(gpg,cipheralgo) } if {$pgp(gpg,digestalgo) != "default"} { lappend arglist --personal-digest-preferences $pgp(gpg,digestalgo) } # compressalgo if {$pgp(gpg,compressalgo) != "default" } { if {$pgp(gpg,compressalgo) == "none"} { lappend arglist -z 0 } else { lappend arglist --personal-compress-preferences $pgp(gpg,compressalgo) } } ldelete arglist {} return $arglist } ####################################################################### # Flags, Commands, Patterns, Settings # # Should config file be parsed set pgp(gpg,parse_config) 1 ####### # Exec ############# # Exec_Batch # Batchmode flags set pgp(gpg,flags_batch) {--batch --status-fd 2 [Pgp_Gpg_Arglist]} # proc Pgp_gpg_PassFdSet {} { upvar tclcmd tclcmd set tclcmd [linsert $tclcmd 2 --passphrase-fd 0] } # proc Pgp_gpg_PassFdUnset {} { } ################### # Exec_Interactive # Interactive flags set pgp(gpg,flags_interactive) {[Pgp_Gpg_Arglist]} # Cleanup output set pgp(gpg,cmd_cleanOutput) { regsub -all "\[\x0d\x07]" $output {} output regexp "gpg:.*\$" $output output set output [string trim $output] } ############### # Exec_KeyList # List pubkeys args prototype set pgp(gpg,args_listPub) {--with-colons --list-keys \"$pattern\"} # List seckeys args prototype set pgp(gpg,args_listSec) {--with-colons --list-secret-keys \"$pattern\"} # Pattern that matches out revoked and nonvalid keys set pgp(gpg,pat_dropKeys) {(^|\n)(pub|sub|sec|ssb|uid):[dren]:[^\n]+} # Where to split up the listKeys raw output to form a list set pgp(gpg,pat_splitKeys) \n # Patterns that match out interesting keys set pgp(gpg,pat_keySec) \ {^(pub|sec):[^:]*:[^:]*:([^:]*):([0-9A-F]+):[^:]*:[^:]*:[^:]*:[^:]*:([^:]+).*$} set pgp(gpg,pat_keySec_sub) \ {^(ssb):[^:]*:[^:]*:([^:]+):([0-9A-F]+):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*.*$} set pgp(gpg,pat_keyPub) $pgp(gpg,pat_keySec) set pgp(gpg,pat_keyPub_sub) \ {^(sub):[^:]*:[^:]*:([^:]+):([0-9A-F]+):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*.*$} set pgp(gpg,pat_uid) \ {^(uid):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]+).*$} # TclCmd to match out userid and keyid set pgp(gpg,cmd_keyMatch) { if [set match [regexp $keypattern $line {} {} algo keyid userid]] { switch $algo { 1 {set algo RSA} 16 {set algo ELG} 17 {set algo DSA} 20 {set algo ELG} } } set match } set pgp(gpg,cmd_keyMatch_sub) { if [set match [regexp $subkeypattern $line {} {} algo keyid]] { switch $algo { 1 {set algo RSA} 16 {set algo ELG} 17 {set algo DSA} 20 {set algo ELG} } } set match } set pgp(gpg,cmd_uidMatch) { regexp $uidpattern $line {} {} userid } ############### # Exec_GetKeys set pgp(gpg,args_exportKey) {--export --armor --textmode -o $file $keyid} ############### # Exec_Encrypt set pgp(gpg,args_encrypt) {[concat -eat -o $out [set recips {}; foreach id [Pgp_Misc_Map key {lindex $key 0} $tokeys] {lappend recips -r $id}; set recips] $in]} ################### # Exec_EncryptSign set pgp(gpg,args_encryptSign) {[concat -east -o $out -u $keyid [set recips {}; foreach id [Pgp_Misc_Map key {lindex $key 0} $tokeys] {lappend recips -r $id}; set recips] $in]} ############ # Exec_Sign set pgp(gpg,args_signClear) {--clearsign --armor --textmode -u $keyid -o $out $in} set pgp(gpg,args_signBinary) {--sign --armor --textmode -u $keyid -o $out $in} #################### # Exec_SignDetached set pgp(gpg,args_signDetached) {-abt -u $keyid -o $out $in} ##################### # Exec_CheckPassword set pgp(gpg,pat_checkError) "(BAD_PASSPHRASE\[^\n]+)\n" ####################### # Exec_DetDecryptKeyid set pgp(gpg,args_getDecryptKeyid) {--dry-run $in} set pgp(gpg,pat_getDecryptKeyid) "NEED_PASSPHRASE \[\[:alnum:]_]+ (\[\[:alnum:]_]+)" set pgp(gpg,pat_getDecryptSym) "NEED_PASSPHRASE_SYM" ############### # Exec_Decrypt set pgp(gpg,args_decrypt) {--status-fd 2 -o $out $in} ##################### >>>>>>>>>>>> DELETE # Exec_DecryptExpect #set pgp(gpg,expectpat,passprompt) "NEED_PASSPHRASE (\[^ \n]*)" #set pgp(gpg,expectpat,conventional) {NEED_PASSPHRASE_SYM} #set pgp(gpg,expectpat,publickey) "Do-Not-Match" #set pgp(gpg,expectpat,secretmissing) "NO_SECKEY" #set pgp(gpg,expectpat,nopgpfile) {BADARMOR|NODATA} #set pgp(gpg,cmd_DecryptExpect) {gpg --no-greeting --status-fd 2 -o $outfile $infile} ############## # Exec_Verify set pgp(gpg,args_verifyOnly) {--verify $in} set pgp(gpg,args_verifyOut) {-o $out $in} ###################### # Exec_VerifyDetached set pgp(gpg,args_verifyDetached) {--verify $sig $text} ################### # Exec_ExtractKeys set pgp(gpg,args_importKey) {--import $file} ######################### # ShowMessage keypattern set pgp(gpg,pat_validKeys) "\n?(ssb|pub|sec|sub|uid)\[^\n]*" ################## # InterpretOutput # command that matches out keyid in pgp output set pgp(gpg,cmd_Keyid) { if {[regexp {GOODSIG ([^ ]*)} $in {} pgpresult(keyid)]} { } elseif {[regexp {BADSIG ([^ ]*)} $in {} pgpresult(keyid)]} { } else {regexp {ERRSIG ([^ ]*)} $in {} pgpresult(keyid)} # Keyservers like only the last four octets of the keyid. if {[info exists pgpresult(keyid)]} { set keyidLength [string length $pgpresult(keyid)] set pgpresult(keyid) [string range $pgpresult(keyid) [expr $keyidLength-8] $keyidLength] } } # command that tailors output to be nice looking set pgp(gpg,cmd_Beauty) { set pgpresult(msg) $in regsub -all "\\\[GNUPG:\\\]\[^\n\]*\n*" $pgpresult(msg) {} pgpresult(msg) regsub -all {gpg: } $pgpresult(msg) {} pgpresult(msg) set pgpresult(msg) [string trim $pgpresult(msg)] } # patterns for interpreting output set pgp(gpg,pat_SecretMissing) {ENC_TO.*DECRYPTION_FAILED} set pgp(gpg,pat_PublicMissing) {ERRSIG} set pgp(gpg,pat_GoodSignature) {GOODSIG} set pgp(gpg,pat_Untrusted) {(TRUST_UNDEFINED|TRUST_NEVER)} set pgp(gpg,pat_BadSignature) {BADSIG} set pgp(gpg,pat_UnknownError) {ERROR} # command that matches out the Originator set pgp(gpg,cmd_User) { regexp {(GOODSIG|BADSIG) [^ ]* ([^\n]*)} $in {} {} user } ################## # WWW_QueryHKPKey set pgp(gpg,args_HKPimport) {--keyserver $server --recv-keys 0x$id} } exmh-2.9.0/lib/timer.bitmap0000644000170700017070000000050213201227060015067 0ustar valdisvaldis#define timer_width 16 #define timer_height 16 #define timer_x_hot 7 #define timer_y_hot 8 static char timer_bits[] = { 0x00, 0x30, 0xe0, 0x73, 0xf8, 0xef, 0x1c, 0xdc, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0xfb, 0x60, 0x83, 0x60, 0x83, 0x60, 0x86, 0x30, 0x86, 0x30, 0x1c, 0x1c, 0xf8, 0x0f, 0xe0, 0x03}; exmh-2.9.0/lib/seditBind.tcl0000644000170700017070000005743713201227060015205 0ustar valdisvaldis# seditBind.tcl # # Support routines to define a set of consistent editing bindings for # Text and Entry widgets # # Copyright (c) 1993 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. # Because we override Entry and Text bindings, make sure we load those first # By auto-loading these procedures we also fault in the global Text and # Entry bindings done by the Tk library code. auto_load tkEntryButton1 auto_load tkTextButton1 proc Sedit_BindInit {} { global sedit exmh foreach editproc [option get . sedit_editprocs {}] { set sedit(key,$editproc) [option get . sedit_key_$editproc {}] } Preferences_Resource sedit(pasteSetsInsert) sedit_pasteSetsInsert 1 Preferences_Resource sedit(typeKillsSel) sedit_typeKillsSel 1 Preferences_Resource sedit(scrollButton) sedit_scrollButton Middle # Don't really need sedit-bindings and local.sedit-bindings anymore # with the use of resources set sedit(defaultfile) $exmh(library)/sedit-bindings set sedit(localfile) $exmh(library)/local.sedit-bindings set sedit(dotfile) ~/.exmh/exmhsedit SeditReadPref Sedit_ClassBindings SeditComposedKeyBindings } proc SeditReadPref {} { global sedit foreach file {defaultfile localfile dotfile} { if [file exists $sedit($file)] { if [catch {uplevel #0 source [glob $sedit($file)]} msg] { Exmh_Status "Error in $sedit($file): $msg" } } } } proc SeditBind { class key body } { global sedit if [catch { foreach seq $sedit(key,$key) { if {$seq == {}} { continue } bind $class $seq $body # Double-bind Meta-key and Escape-key if [regexp {} $seq match letter] { bind $class <$letter> $body } # Make leading keystroke harmless if [regexp {(<.+>)<.+>} $seq match prefix] { bind $class $prefix break } } } err] { if ![info exists sedit(key,$key)] { Exmh_Debug "Bind $class $key: $err" } else { Exmh_Debug "Bind $class $key $sedit(key,$key): $err" } } } proc Sedit_TagBindings { w tag } { $w tag bind $tag {WidgetTextSelBegin %W %x %y char} $w tag bind $tag {WidgetTextSelBegin %W %x %y word} $w tag bind $tag {WidgetTextSelBegin %W %x %y line} $w tag bind $tag {WidgetTextSelMotion %W %x %y} $w tag bind $tag {WidgetTextSelDone %W} } proc SeditTextBindings { draft t } { global sedit quote # Define binding tags: # SeditText - simple editor commands and data entry # TScroll - drag scrolling # TSelect - text selection # $t - send message binding # toplevel - not used # all - not used because it has focus-change bindings on bindtags $t [list $t SeditText TSelect TScroll [winfo toplevel $t]] SeditBind $t sendMsg "SeditSend {$draft} {$t} 0 ; break" SeditBind Entry sendMsg { } SeditBind $t abortMsg "SeditAbort {$draft} {$t} ; break" SeditBind Entry abortMsg { } SeditBind $t quoteMsg "SeditInsertFile {$draft} {$t} {$quote(filename)} ; break" SeditBind Entry quoteMsg { } # redisplay debug loggin if {[info commands log_dump] == "log_dump"} { bind $t {log "Key %A %K"} bind $t {log "Enter %W"} bind $t {log "Leave %W"} bind $t {log "ButtonPress %W"} bind $t {log "ButtonRelease %W"} } } proc Sedit_ClassBindings { } { global sedit foreach class {SeditText Entry} { foreach b [bind $class] { bind $class $b "" } } # This is needed because there are no Text bindings at this # point - they have not been faulted in yet from the library - # So erasing them now doesn't help. We use an alternate class. set tclass SeditText # Modification bindings bind $tclass { SeditKill?Sel %W Text_Insert %W insert \n; %W yview -pickplace insert SeditDirty %W } bind $tclass { if [%W compare insert <= hlimit] { Text_MoveInsert %W insert+1line Text_MoveInsert %W "insert lineend" } else { Text_Insert %W insert \t %W yview -pickplace insert SeditDirty %W } } bind $tclass { if [%W compare insert <= hlimit] { Text_MoveInsert %W hlimit+1line } else { Text_Insert %W insert %A; %W yview -pickplace insert SeditDirty %W } } bind $tclass [bind $tclass ] # These bindings ensure that unbound control, meta, and escape # sequences don't do anything. foreach ignore { } { bind $tclass $ignore { } ;# no-op bind Entry $ignore { } ;# no-op } SeditBind $tclass selpaste { Text_Yank %W SeditDirty %W } SeditBind Entry selpaste { if [catch {%W insert insert [selection get]}] { if [catch {%W insert insert [selection get -selection CLIPBOARD]}] { catch {%W insert insert [cutbuffer get]} } } } # When is pressed, wait for one char and insert the # compose key ^ SeditBind $tclass { bind SeditText { if {"%%A" != "{}"} { SeditComposedKey %%W "^" "%%A" } } } # When is pressed, wait for one char and insert the # compose key " SeditBind $tclass { bind SeditText { if {"%%A" != "{}"} { SeditComposedKey %%W "\"" "%%A" } } } # when the compose char is pressed, wait for 2 chars # (the first may be part of the composechar event) SeditBind $tclass composechar { bind SeditText { if {"%%A" != "{}"} { if {"%A" == "{}"} { bind SeditText { if {"%%%%A" != "{}"} { SeditComposedKey %%%%W "%%A" "%%%%A" } } } else { SeditComposedKey %%W "%A" "%%A" } } } } SeditBind $tclass seldelete { Text_KillSelection %W SeditDirty %W } SeditBind Entry seldelete { catch {%W delete sel.first sel.last} } SeditBind $tclass backspace { if ![SeditKill?Sel %W] { Text_Delete %W insert-1c insert } %W yview -pickplace insert SeditDirty %W } SeditBind Entry backspace { tkEntryBackspace %W } SeditBind $tclass openline { Text_Insert %W insert \n Text_MoveInsert %W insert-1c SeditDirty %W } SeditBind Entry openline { info library } SeditBind $tclass deleol { if {! [SeditKill?Sel %W]} { if {[%W index insert] == [%W index {insert lineend}]} { Text_Delete %W insert insert+1c 1 } else { Text_Delete %W insert "insert lineend" 1 } } %W yview -pickplace insert SeditDirty %W } SeditBind Entry deleol { %W delete insert end } SeditBind $tclass delbol { if {! [SeditKill?Sel %W]} { if {[%W index insert] == [%W index {insert linestart}]} { Text_Delete %W insert-1c insert 1 } else { Text_Delete %W "insert linestart" insert 1 } } %W yview -pickplace insert SeditDirty %W } SeditBind Entry delbol { %W delete 0 insert } SeditBind $tclass delwordforw { if {! [SeditKill?Sel %W]} { Text_Delete %W insert [Text_NextWord %W insert] 1 } SeditDirty %W } SeditBind Entry delwordforw { } SeditBind $tclass delwordback { if {! [SeditKill?Sel %W]} { Text_Delete %W [Text_PrevWord %W insert] insert 1 } %W yview -pickplace insert SeditDirty %W } SeditBind Entry delwordback { %W delete [string wordstart [%W get] [expr [%W index insert] - 1]] \ insert tkEntrySeeInsert %W } SeditBind $tclass delchar { if {! [SeditKill?Sel %W]} { Text_Delete %W insert } %W yview -pickplace insert SeditDirty %W } SeditBind Entry delchar { %W delete insert } SeditBind $tclass transpose { Text_TransposeChars %W SeditDirty %W } SeditBind $tclass transemacs { Text_TransposeCharsEmacs %W SeditDirty %W } SeditBind Entry transpose { SeditEntryTranspose %W } SeditBind Entry transemacs { SeditEntryTranspose %W emacs } SeditBind $tclass transword { Text_TransposeWords %W SeditDirty %W } SeditBind Entry transword { } # Motion bindings SeditBind $tclass bof { Text_MoveInsert %W 1.0 } SeditBind Entry bof { } SeditBind $tclass eof { Text_MoveInsert %W end } SeditBind Entry eof { } SeditBind $tclass linestart { Text_MoveToBOL %W } SeditBind Entry linestart { %W icursor 0 tkEntrySeeInsert %W } SeditBind $tclass lineend { Text_MoveInsert %W "insert lineend" } SeditBind Entry lineend { %W icursor end tkEntrySeeInsert %W } set sedit(lastpos,Text) {} SeditBind $tclass up1line { Text_MoveInsert %W insert-1line } SeditBind Entry up1line { } SeditBind $tclass down1line { Text_MoveInsert %W insert+1line } SeditBind Entry down1line { } SeditBind $tclass backword { Text_MoveInsert %W [Text_PrevWord %W insert] } SeditBind Entry backword { set string [%W get] set curs [expr [%W index insert]-1] if {$curs < 0} return for {set x $curs} {$x > 0} {incr x -1} { if {([string first [string index $string $x] " \t"] < 0) && ([string first [string index $string [expr $x-1]] " \t"] >= 0)} { break } } %W icursor $x tkEntrySeeInsert %W } SeditBind $tclass forwword { Text_MoveInsert %W [Text_NextWord %W insert] } SeditBind Entry forwword { set string [%W get] set curs [expr [%W index insert]+1] set len [string length $string] if {$curs < 0} return for {set x $curs} {$x < $len} {incr x} { if {([string first [string index $string $x] " \t"] < 0) && ([string first [string index $string [expr $x+1]] " \t"] >= 0)} { break } } %W icursor $x tkEntrySeeInsert %W } SeditBind $tclass backchar { Text_MoveInsert %W insert-1c } SeditBind Entry backchar { set x [%W index insert] if {$x > 0} { incr x -1 %W icursor $x tkEntrySeeInsert %W } } SeditBind $tclass forwchar { Text_MoveInsert %W insert+1c } SeditBind Entry forwchar { set x [%W index insert] incr x %W icursor $x tkEntrySeeInsert %W } SeditBind $tclass up1page { Widget_TextPageUp %W } SeditBind Entry up1page { } ;# no-op SeditBind $tclass down1page { Widget_TextPageDown %W } SeditBind Entry down1page { } ;# no-op bind $tclass { SeditInsert %W %A } bind $tclass { SeditInsert %W %A } if {[info commands kinput_start] == "kinput_start"} { bind $tclass {SeditKinput_start %W} bind $tclass {SeditKinput_start %W} bind $tclass {SeditKinput_start %W} } SeditBind SeditText addrexpand {Addr_KeyExpand %W} SeditBind SeditText format {Sedit_FormatParagraph %W} SeditBind SeditText highlight { SeditBeautify %W } foreach cmd [info commands Hook_TextBind*] { $cmd $tclass } # Selection bindings set tclass TSelect SeditBind $tclass selcopy { catch {clipboard clear ; clipboard append [Text_Selection]} cutbuffer set [Text_Selection] } SeditBind Entry selcopy { catch {clipboard clear ; clipboard append [Text_Selection]} cutbuffer set [Text_Selection] } SeditBind $tclass selclear { Text_LoseSelection %W } SeditBind Entry selclear { %W select clear } SeditBind $tclass selstart { Text_LoseSelection %W; WidgetTextSelStart %W insert char } SeditBind Entry selstart { %W select clear ; %W select from insert } SeditBind $tclass selforw { Text_SelectTo %W insert Text_SelectionEnd %W 1 } SeditBind Entry selforw { set x [%W index insert] incr x %W icursor $x %W select to insert } SeditBind $tclass selback { Text_SelectTo %W insert Text_SelectionEnd %W 1 } SeditBind Entry selback { set x [%W index insert] incr x -1 %W icursor $x %W select to insert } SeditBind $tclass selextend { Text_SelectTo %W insert Text_SelectionEnd %W 1 Text_SelectionEnd %W 1 } SeditBind Entry selextend { %W select to insert } bind $tclass {WidgetTextSelBegin %W %x %y char} bind $tclass {WidgetTextSelBegin %W %x %y word} bind $tclass {WidgetTextSelBegin %W %x %y line} bind $tclass {WidgetTextSelMotion %W %x %y} bind $tclass {WidgetTextSelDone %W} bind $tclass {WidgetTextSelAgain %W %x %y} bind $tclass {WidgetTextSelMotion %W %x %y} bind $tclass {WidgetTextSelDone %W} bind $tclass {Text_MoveInsert %W @%x,%y noclear} bind Entry {SeditEntryInsert %W %A} bind Entry {SeditEntryInsert %W %A} bind Entry {SeditEntrySelect %W %x} bind Entry {SeditEntryShiftSelect %W %x} bind Entry {SeditEntryDrag %W %x} bind Entry {SeditEntryDrag %W %x} bind Entry {SeditEntryWordSelect %W %x} bind Entry {SeditEntryLineSelect %W %x} # Hack. This has been here all the time as part of the default # entry class bindings. Should be settable though. bind Entry {%W delete 0 end} # Scroll bindings set tclass TScroll # Clear default scroll bindings foreach seq { } { bind $tclass $seq {} bind Entry $seq {} } global exwin switch -- $sedit(scrollButton) { Middle { set b 2 } Right { set b 3 } ShiftMiddle { set b shift2 } None { set b {} } } # focus debug hack if {([info command log_dump] == "log_dump")} { bind $tclass { if [catch { if ![info exists logID] {set logID 0} while {[file exists /tmp/log$logID]} { incr logID } log SEDIT "/tmp/log$logID" set out [open /tmp/log$logID w] puts $out [log_dump] close $out Exmh_Status "Debug log in /tmp/log$logID" incr logID } err] { Exmh_Status $err } } } if {$b == 2 || $b == 3} { bind $tclass { WidgetTextMark %W %y } bind $tclass { WidgetTextDragto %W %y $exwin(scrollSpeed) } bind $tclass { WidgetTextMark %W %y set widgetText(%W,paste?) 0 } bind $tclass { WidgetTextDragto %W %y [expr $exwin(scrollAccel)*$exwin(scrollSpeed)] } bind Entry {%W scan mark %x} bind Entry {%W scan dragto %x} } elseif {$b == "shift2"} { set b 2 bind $tclass {WidgetTextMark %W %y} bind $tclass \ {WidgetTextDragto %W %y $exwin(scrollSpeed)} bind Entry {%W scan mark %x} bind Entry {%W scan dragto %x} } bind $tclass {+ set widgetText(%W,time) %t set widgetText(%W,paste?) 1 set widgetText(%W,x) %x set widgetText(%W,y) %y } bind $tclass { if [info exists widgetText(%W,paste?)] { if {$widgetText(%W,paste?) && (%t - $widgetText(%W,time)) < 500 && (abs(%x - $widgetText(%W,x)) < 3) && (abs(%y - $widgetText(%W,y)) < 3)} { catch { if $sedit(pasteSetsInsert) { Text_MoveInsert %W @%x,%y noclear } Text_Yank %W SeditDirty %W } } } } bind Entry {+ set widgetText(%W,time) %t set widgetText(%W,paste?) 1 set widgetText(%W,x) %x set widgetText(%W,y) %y } bind Entry { if [info exists widgetText(%W,paste?)] { if {$widgetText(%W,paste?) && (%t - $widgetText(%W,time)) < 500 && (abs(%x - $widgetText(%W,x)) < 3) && (abs(%y - $widgetText(%W,y)) < 3)} { if [catch { %W insert insert [selection get] }] { if [catch {%W insert insert [cutbuffer get]}] { # catch {%W insert insert $sedit(killbuf)} } } } } } } proc SeditEntryInsert { w a } { global sedit if {$a != ""} { if {$sedit(typeKillsSel)} { catch {$w delete sel.first sel.last} } $w insert insert $a tkEntrySeeInsert $w } } proc SeditEntrySelect { w x } { global sedit set sedit(selectmode,$w) char $w icursor @$x $w select from @$x set sedit(anchor,$w) [$w index @$x] if {[lindex [$w config -state] 4] == "normal"} {focus $w} } proc SeditEntryShiftSelect { w x } { global sedit if ![info exists sedit(selectmode,$w)] { return } if {$sedit(selectmode,$w) == "word"} { set nx [$w index @$x] set ix [SeditEntryFindWord $w $x [expr {$nx >= $sedit(anchor,$w)}]] } else { set ix [$w index @$x] } $w select adjust $ix } proc SeditEntryDrag { w x } { global sedit if ![info exists sedit(selectmode,$w)] { return } if {$sedit(selectmode,$w) == "word"} { set nx [$w index @$x] set ix [SeditEntryFindWord $w $x [expr {$nx >= $sedit(anchor,$w)}]] } else { set ix [$w index @$x] } $w select to $ix } proc SeditEntryWordSelect { w x } { global sedit set sedit(selectmode,$w) word set ix [SeditEntryFindWord $w $x 0] $w select from $ix $w icursor $ix tkEntrySeeInsert $w $w select to [SeditEntryFindWord $w $x 1] set sedit(anchor,$w) $ix } proc SeditEntryFindWord { w x {forw 1} } { set string [$w get] set ix [$w index @$x] set start 1 set char [string index $string $ix] if {$forw} { while {[string length $char] && ![regexp {[ ]} $char]} { incr ix set char [string index $string $ix] set start 0 } } else { while {[string length $char] && ![regexp {[ ]} $char]} { incr ix -1 set char [string index $string $ix] set start 0 } } if {! $start} { if {$forw} { incr ix -1 } else { incr ix 1 } } return $ix } proc SeditEntryLineSelect { w x } { global sedit set sedit(selectmode,$w) char ;# yes, char $w select from 0 $w select to end $w icursor 0 tkEntrySeeInsert $w } proc SeditEntryTranspose { w {how ""} } { set _x [$w index insert] if {$how == "emacs"} { # Transpose two characters around insert and advance insert incr _x -1 if {$_x < 0} {set _x 0} set _c [string index [$w get] $_x] $w delete $_x $w icursor [expr [$w index insert] +1] $w insert insert $_c } else { # Transpose two characters before insert incr _x -2 if {$_x < 0} {set _x 0} set _c [string index [$w get] $_x] $w delete $_x incr _x $w insert $_x $_c } tkEntrySeeInsert $w } proc SeditKill?Sel { w } { global sedit if $sedit(typeKillsSel) { return [Text_KillSelection $w] } else { return 0 } } proc SeditInsert { w a } { global sedit if {"X$a" != "X"} { if $sedit(typeKillsSel) { Text_KillSelection $w } scan $a %c X if {$X > 127} { set sedit($w,8bit) 1 } if {[string compare $sedit($w,format) "OnType"] == 0} { set i [SeditCount $w insert] if {$i >= $sedit(lineLength)} { if [$w compare insert <= hlimit] { set stuff "\n " } else { set stuff \n } if [catch {$w insert wordbreak $stuff}] { $w insert insert $stuff } $w mark unset wordbreak } $w insert insert $a if [regexp $sedit(wordbreakpat) $a] { $w mark set wordbreak insert $w mark gravity wordbreak left } } else { $w insert insert $a } $w yview -pickplace insert set sedit($w,dirty) 1 } } proc SeditCount {w mark} { set string [$w get "$mark linestart" $mark] set i 0 foreach c [split $string {}] { if {"$c" == "\t"} { set i [expr $i/8 + 8] } else { incr i } } return $i } proc SeditMarkClean { t } { global sedit set sedit($t,dirty) 0 } proc SeditDirty { t } { global sedit set sedit($t,dirty) 1 } proc SeditIsDirty { t } { global sedit return $sedit($t,dirty) } proc Sedit_Pref {} { global sedit if [Exwin_Toplevel .seditpref "Simple Edit Preferences" Pref] { Widget_AddBut .seditpref.but save "Save" {SeditPrefSave} Widget_AddBut .seditpref.but help "Help" {SeditPrefHelp} Widget_AddBut .seditpref.but event "Events" {SeditEventHelp} Widget_Label .seditpref.but label {left fill} \ -text "Text and Entry class bindings" set f2 [Widget_Frame .seditpref tog] pack $f2 -padx 10 -pady 4 -fill none $f2 configure -bd 2 Widget_Label $f2 label {left padx 10} -text "Options" Widget_CheckBut $f2 type "Type Kills SEL" sedit(typeKillsSel) {left padx 4} Widget_CheckBut $f2 paste "Paste Sets Insert" sedit(pasteSetsInsert) {left padx 4} set f2 [Widget_Frame .seditpref tog2 Frame {top expand fillx padx 10 pady 4}] $f2 configure -bd 2 pack $f2 -padx 10 -pady 4 -fill none Widget_Label $f2 label {left padx 10} -text "Scroll Button" Widget_RadioBut $f2 but2 "Middle" sedit(scrollButton) {left padx 4} Widget_RadioBut $f2 but3 "Right" sedit(scrollButton) {left padx 4} Widget_RadioBut $f2 shift2 "Shift-Middle" sedit(scrollButton) {left padx 4} Widget_RadioBut $f2 none "None" sedit(scrollButton) {left padx 4} set f [Widget_Frame .seditpref p Dialog] $f configure -bd 10 set lr [Widget_SplitFrame $f Left Right] set left [lindex $lr 0] set right [lindex $lr 1] set width 0 foreach item [array names sedit] { if [regexp ^key $item] { set name [lindex [split $item ,] 1] set w [string length $name] if {$w > $width} { set width $w } } } set size 0 if [info exists sedit(key,delword)] { lappend sedit(key,delwordforw) $sedit(key,delword) unset sedit(key,delword) } foreach item [lsort [array names sedit]] { if [regexp ^key $item] { set name [lindex [split $item ,] 1] incr size set keystroke $sedit($item) set frame [lindex $lr [expr {$size % 2}]] SeditPrefItem $frame $width $name $keystroke } } } } proc SeditPrefItem { frame width name keystroke } { global sedit Widget_Frame $frame $name Preference Widget_Label $frame.$name label {left} -text $name -width $width Widget_Entry $frame.$name entry {right expand fill} set sedit(entry,$name) $frame.$name.entry $frame.$name.entry insert 0 $keystroke } proc SeditPrefHelp {} { Help Seditpref "Simple Edit Bindings Help" } proc SeditPrefSave { } { global sedit # Save it set out [open $sedit(dotfile) w] foreach item [array names sedit] { if [regexp ^key $item match] { set name [lindex [split $item ,] 1] set entry $sedit(entry,$name) set keystrokes [$entry get] puts $out [list set sedit($match,$name) $keystrokes] } } puts $out "set sedit(pasteSetsInsert) $sedit(pasteSetsInsert)" puts $out "set sedit(typeKillsSel) $sedit(typeKillsSel)" puts $out "set sedit(scrollButton) $sedit(scrollButton)" close $out Exwin_Dismiss .seditpref # Apply it to current session SeditReadPref Sedit_ClassBindings } proc SeditKinput_start { w } { global sedit # modified by k.furukawa, jan.1995. for automatic iso-2022-jp detection. # sedit($window, Acharset) is initialized with {} in Sedit_Start. # once kinput2 is used, the message header will have "charset=iso-2022-jp" # if you set "on" for "specify charset ..." in sedit preference. if [catch {kinput_start $w over} msg] { Exmh_Status "kinput2 failed: $msg" return } set sedit($w,Acharset) iso-2022-jp } proc SeditEventHelp {} { set t .seditevent.text if [Exwin_Toplevel .seditevent "Event Helper" Pref] { Widget_SimpleText .seditevent text {expand fill} -width 40 -height 10 bind $t {SeditEventFeedback %W %K %A ; break} } $t delete 1.0 end $t insert 1.0 "Type into this window to see what events\nare generated by your keyboard\n***\n" } proc SeditEventFeedback {t keysym char} { $t insert end "Keysym $keysym " if {[string length $char] == 0} { switch -glob -- $keysym { Control* {set mod Control} Alt* {set mod Meta} Shift* {set mod Shift} } if [info exists mod] { $t insert end "Modifier $mod" } $t insert end \n } else { $t insert end "Char \"$char\"\n" } $t yview -pickplace end } exmh-2.9.0/lib/mailcap.tcl0000644000170700017070000003417113201227060014674 0ustar valdisvaldis# mailcap parsing suite # by Marc VanHeyningen # May 1994 # Use and redistribute freely # # This is a package of routines in Tcl for handling mailcap files for use in # manipulating MIME objects. It was written with incorporation into Exmh # and maybe TkWWW in mind, but could work for any Tcl program that deals # with MIME objects. If you incorporate it into something and find it works # well, I'd be interested in hearing about it. # # This package attempts to be faithful to the specification for both # MIME (RFC 1521) and mailcap files (RFC 1524; this code actually # includes some features from a later draft.) The only real limitation # is that it doesn't support the %F semantics from appendix A; however, # it does support %M, which is arguably superior anyway. # # SIMPLE USE: # Obviously, load this file. You may wish to change the variable # "mailcap_default_path" to include some specific per-application # mailcap file. # # The procedure mailcap_load will read in all the rules, attempting to # prune down the number of rules to store by evaluating test conditions # ahead of time where possible. The rules are stored in the global # associative array mailcap_rules; subsequent changes in the mailcap # file will not take effect unless mailcap_load is invoked again. # # The procedure mailcap_parse_content_type will do most of the parsing # of the MIME Content-Type header for you. Your program should pull off # the "Content-Type:" label and put together line continuations per RFC # 822, but mailcap will do the MIME-specific parsing. # mailcap_parse_content_type takes two arguments; the entire header (minus the # label) and the name of an associative array into which the parameters # will be placed. The procedure returns the content type and subtype. # # The primary procedure is mailcap_getrule; it is how you extract an # appropriate rule from the mailcap file. It takes as arguments: # # - The content-type (as returned by mailcap_parse_content_type) # - The name of the array of parameters (from mailcap_parse_content_type) # - The method to do (e.g. "compose", "print", "description", # "x11-bitmap". The empty string finds the view command.) # - The name of an array to store additional fields from the mailcap # entry in. # - The temporary filename containing the unencoded body # - (optional) A list of pairs of content-types and filenames of the # body-parts of a multipart message, for use in %F substitution (not # often used, ignore freely) # - (optional) A list of pairs of filenames of headers and bodies of # the body-parts of a multipart message, for use in %M substitution # (not often used, ignore freely) # # SIMPLE EXAMPLE : # The following line is from a mailcap file: # text/richtext; richtext %s; copiousoutput # # % source mailcap.tcl # % mailcap_load # % set ct [mailcap_parse_content_type {text/richtext; charset = "US-ASCII"} p] # text/richtext # % set p(charset) # US-ASCII # % set cmd [mailcap_getrule $ct p "" at "/tmp/blah.1234"] # richtext /tmp/blah.1234 # % info exists at(copiousoutput) # 1 # % info exists at(needsterminal) # 0 # # SIMPLE USE IN A MAILER: # # ... somehow set up headers ... # # set content_type [mailcap_parse_content_type $header(content-type) \ # content_params]; # # ... attempt to display the content type using built in procedures ... # ... store content in file $body_filename ... # # set cmd [mailcap_getrule $content_type content_params "" cmd_atribs \ # $body_filename]; # if [info exists cmd_atribs(needsterminal)] { # exec "xterm" "-e" "sh" "-c" $cmd; # } {if [info exists cmd_atribs(copiousoutput)] { # exec "sh" "-c" "$cmd | xless"; # } { # exec "sh" "-c" $cmd; # } # ... # # Obviously a real mailer would do some more sophisticated things, such # as use "catch" in appropriate places to handle failures of various # rule lookups. # # Note that the "nametemplate" field may be useful in generating # temporary files with descriptive names: # # % mailcap_getrule "image/gif" bogus "nametemplate" bogus2 "/tmp/f1234" # /tmp/f1234.gif # # For composing agents, this functionality may be reversed with the # procedure mailcap_guess_content_type. Note that this means using # mailcap information in a manner it wasn't really intended for, but # which can be useful. The results should never be taken as # authoritative, but may be a useful default in prompting a user what # the content-type of a file is: # # % mailcap_guess_content_type "/usr/local/neat/writeup.ps" # application/postscript # proc mailcap_backslash_undo {string} { set buffer $string regsub -all {\\(.)} $string {\1} buffer; return $buffer; } proc mailcap_normalize {string} { return [string trim [mailcap_backslash_undo $string] " \t"]; } proc mailcap_normalize_full {string} { return [string tolower [mailcap_normalize $string]]; } proc mailcap_load {} { global mailcap_rules mailcap_default env exmh catch {unset mailcap_rules}; if [info exists env(MAILCAPS)] { set mailcap_path $env(MAILCAPS) } else { set mailcap_path $exmh(userLibrary)/user.mailcap:$env(HOME)/.mailcap:$exmh(library)/local.mailcap:$exmh(library)/mailcap/:$mailcap_default } if [info exists env(METAMAIL_HOME)] { append mailcap_path :$env(METAMAIL_HOME)/mailcap } foreach mailcap_file [split $mailcap_path :] { catch {close $fh} if {![file exists $mailcap_file] || [file isdirectory $mailcap_file] || [catch {open $mailcap_file} fh]} { continue } set buf [read $fh]; # wrap line continuations together by deleting backslash-newlines set subpat "((^|\[^\\\\\])(\\\\\\\\)*)\\\\\n"; regsub -all "$subpat" $buf {\1} rules; set forget_it 0; foreach rule [split $rules \n] { if [regexp {^([ \t]*)$|^#} $rule] {continue}; regsub -all {((^|[^\\])(\\\\)*)\;} $rule "\\1\n" fields; set field_list [split $fields "\n"]; set rule_content_type [mailcap_normalize_full [lindex $field_list 0]]; if [regexp {^(.+)/(.+)$} $rule_content_type bogus rule_content_primary \ rule_content_secondary] {} { # handle implicit wildcards set rule_content_primary $rule_content_type; set rule_content_secondary "*"; } set rule_viewer [mailcap_normalize [lindex $field_list 1]]; set rule_fields {}; foreach rule_field [lrange $field_list 2 end] { if [regexp {^([^=]+)=(.*)$} $rule_field bogus field_name field_value] { set field_name [mailcap_normalize_full $field_name]; regexp {^\"([^\"]+)\"$} [string trim $field_value] bogus field_value; if {$field_name == "test"} { if [regexp {(^|[^\\])(\\\\)*\%} $field_value] {} { if [catch {exec "sh" "-c" [mailcap_normalize $field_value]}] { set forget_it 1; break; } { continue; } } } lappend rule_fields [list $field_name $field_value]; } { set rule_field [mailcap_normalize_full $rule_field]; if {$rule_field == "needsx11"} { if [info exists env(DISPLAY)] {continue} { set forget_it 1; break; } } lappend rule_fields $rule_field; } } if {$forget_it == 1} { set forget_it 0; } { lappend mailcap_rules($rule_content_primary) \ [concat [list $rule_content_secondary $rule_viewer] $rule_fields]; } } } } # Note that quoting parameters is done with single quotes for # security, so that shell metacharacters should not have # problematic effects at the shell level. proc mailcap_quote_param {string} { regsub -all "\'" [string trim $string " \t"] "\'\"\'\"\'" buffer; # These are also used in regsubs, so protect against specials there, esp & regsub -all {[][&*+?()]} $buffer {\\&} buffer return "\'$buffer\'"; } proc mailcap_normalize_command {method string content_type body_filename f_multi_list m_multi_list params} { upvar $params p; set f_multi_files ""; foreach file_pair $f_multi_list { set f_multi_files \ "$f_multi_files [mailcap_quote_param [lindex $file_pair 0]] [lindex $file_pair 1]"; } set m_multi_files ""; foreach file_pair $m_multi_list { set m_multi_files "$m_multi_files [join $file_pair]"; } set num_parts [llength $f_multi_list]; if {$num_parts == 0} {set num_parts [llength $m_multi_list]}; set file_used [expr \ [regsub -all {((^|[^\\])(\\\\)*)%s} $string "\\1$body_filename" string] + \ [regsub -all {((^|[^\\])(\\\\)*)%F} $string "\\1$f_multi_files" string] + \ [regsub -all {((^|[^\\])(\\\\)*)%M} $string "\\1$m_multi_files" string]]; regsub -all {((^|[^\\])(\\\\)*)%t} $string "\\1$content_type" string; regsub -all {((^|[^\\])(\\\\)*)%n} $string "\\1$num_parts" \ string; # Note that this will fail with parameters containing the {} characters, # which is legal but not used and rather bizarre. while {[regexp {((^|[^\\])(\\\\)*)%\{([^ \{\}\;]+)\}} "$string" \ full prelude junk1 junk2 attribute]} { if [info exists p($attribute)] { regsub $full $string "$prelude[mailcap_quote_param $p($attribute)]" \ string; } { # instantiate undefined parameters as the empty string regsub $full $string "$prelude\'\'" string; } } if {$file_used != 0} {} { if {($method == "") || ($method == "print") || ($method == "edit")} { set string "($string) < $body_filename"; } { if {($method == "compose") || ($method == "composetyped") || \ ($method == "edit")} { set string "($string) > $body_filename"; } } } return $string; } proc mailcap_parse_content_type {content_type_header parameters} { upvar $parameters p; regsub -all "\[ \t\n\]" $content_type_header " " content_type_header; if ![regexp {^([^;]+)(.*)$} $content_type_header bogus content_type params] { return text/plain } set content_type [string tolower [string trim $content_type " "]]; # ensure space at the end for ease of parsing set params "$params "; while {[regexp {^[ \;]*([^\;\= ]+) *\= *(.*)$} $params bogus attribute rest]} { set attribute [mailcap_normalize_full $attribute]; if {[string index $rest 0] == "\""} { if {[regexp -indices {[^\\](\\\\)*(\")} $rest bogus1 bogus2 quotepos]} { set quotepos [lindex $quotepos 0]; set value [mailcap_backslash_undo [string range $rest 1 \ [expr $quotepos - 1]]]; set params [string range $rest [expr $quotepos + 1] end]; } { return -code error "Bad quoted paramater in $params"} } { if {[regexp -indices {[ \;]} $rest endpos]} { set endpos [lindex $endpos 0]; set value [string range $rest 0 [expr $endpos - 1]]; set params [string range $rest $endpos end]; } { return -code error "Bad paramater line $params"} } set p($attribute) $value; } return $content_type; } proc mailcap_getrule {content_type params method field_array body_filename {f_multipart_filenames {}} {m_multipart_filenames {}}} { global mailcap_rules env; upvar $field_array fa; upvar $params p if [regexp {^(.+)/(.+)$} $content_type bogus primary secondary] {} { # cop-out to handle incorrect but sometimes used primary types only set primary $content_type; set secondary "*"; } if [info exists mailcap_rules($primary)] {} { return -code error "No rules for primary type $primary" } foreach rule $mailcap_rules($primary) { set rule_secondary [lindex $rule 0]; if {($secondary != $rule_secondary) && ($rule_secondary != "*")} { continue; } set fa() [lindex $rule 1]; # Ignore empty view-commands; note that metamail won't handle this if {[string length $fa()] == 0} {unset fa()}; set forget_it 0; foreach field [lrange $rule 2 end] { set field_name [lindex $field 0]; if {$field_name == ""} {continue} set field_value [lindex $field 1]; set fa($field_name) [mailcap_normalize $field_value]; } if [info exists fa($method)] {} {set forget_it 1} # note we don't test needsx11 here because we did that at load time if {($forget_it == 0) && [info exists fa(test)]} { set test_cmd [mailcap_normalize_command "test" \ $fa(test) $content_type $body_filename \ $f_multipart_filenames $m_multipart_filenames p]; if [catch {exec "sh" "-c" $test_cmd}] { set forget_it 1 } } if {$forget_it == 1} { catch {unset fa}; continue; } if [info exists fa($method)] { if [catch {mailcap_normalize_command $method $fa($method) \ $content_type $body_filename $f_multipart_filenames \ $m_multipart_filenames p} cmd] {} { return $cmd; } } } if {$method == {}} { set method view } return -code error "Could not find $method rule for $content_type"; } proc mailcap_guess_content_type {filename} { global mailcap_rules; foreach primary [array names mailcap_rules] { foreach rule $mailcap_rules($primary) { set secondary [lindex $rule 0]; foreach field [lrange $rule 2 end] { set field_name [lindex $field 0]; if {$field_name == "nametemplate"} { set field_value [lindex $field 1]; if [string match "%s" $field_value] continue regsub -all {([.()?*+|])} $field_value {\\\1} field_value regsub {%s} $field_value {.*} field_value; if [regexp -nocase "^$field_value\$" $filename] { return "$primary/$secondary"; } } } } } return -code error "Unable to match $filename with any rules"; } proc mailcap_checkrule {content_type params method args} { global mailcap_rules env; if [regexp {^(.+)/(.+)$} $content_type bogus primary secondary] {} { # cop-out to handle incorrect but sometimes used primary types only set primary $content_type; set secondary "*"; } if [info exists mailcap_rules($primary)] {} { return 0 } foreach rule $mailcap_rules($primary) { set rule_secondary [lindex $rule 0]; if {($secondary != $rule_secondary) && ($rule_secondary != "*")} { continue; } if {$method == {}} { return 1 ;# Assume a view method is defined } foreach field [lrange $rule 2 end] { set field_name [lindex $field 0]; if {[string compare $field_name $method] == 0} { return 1 } } } return 0 } exmh-2.9.0/lib/pgpExec.tcl0000644000170700017070000007543313201227060014667 0ustar valdisvaldis# pgpInterface.tcl -- # created by monnier@didec26.epfl.ch on Mon Dec 12 17:34:38 1994 # # # # $Log$ # Revision 1.22 2008/06/18 10:06:15 az143 # patch from debian: added support for gnupg's gpg-agent # # Revision 1.21 2005/01/01 20:16:20 welch # Based on patches from Alexander Zangerl # lib/pgpGpg.tcl: # lib/pgpPgp5.tcl: # fix of an old pgp problem where recipients were duplicated when # pgp is run in interactive mode # lib/extrasInit.tcl: a small documentation improvement for the # pgp(getextcmd) functionality. # faces(xfaceProg) gains a default (uncompface -X) # lib/pgpExec.tcl: fix for http://bugs.debian.org/164210: multiple gpg # subkeys and passphrases. exmh would not ask for the right passphrase. # lib/addr.tcl: ldap options gain defaults that are compatible with # debian's openldap config # lib/mh.tcl: add Msg-Protect and Folder-Protect to the default .mh_profile # that is generated when setting up new users. # # (These changes are inspired by a patch from Alexander, but not the same) # lib/inc.tcl: use $install(dir,bin) to specify an absolute path to # the inc.expect script # lib/seditExtras.tcl: use $install(dir,bin) to specify an absolute path to # the exmh-async script # lib/mime.tcl: use $install(dir,bin) to specify an absolute path to # the ftp.expect script. # Also changed MimeMakeBoundary to use [clock seconds] instead of # re-writing the output of [exec date]. # # Revision 1.20 2003/02/18 06:50:43 welch # extrasInit.tcl, pgp.tcl - picked up pgp(extpass) patch from Alexander Zangerl # flist.tcl - FlistFindSeqsInner added check to eliminate calls to # Seq_Set if the sequence information for a folder hasn't changed # ftoc.tcl - Changed msgtolinecache and linetomsgcache so that # they have no entries for empty ({}) mappings. I was running into # a mapping for the last text widget line that didn't contain a message # and ended up messing up incremental folder scans # Ftoc_MsgNumber doesn't cache anything if there is no mapping # Retrieved FtocShowUnseen from exmh-2.5 and use that for the # unseen sequence instead of the more general search # main.tcl - a slight varition on the fix that slipcon made to the # millisecond time stamps. # mh.tcl - rooted out an "array unset" that doesn't work in Tcl 8.0 # thread.tcl - fixed call to Flist_ForgetSequence (changed to Seq_Forget) # Minor HTML cleanup, including pointer to the Wiki. # I added comments to several files that identify old exmh APIs, including # flist.tcl, folder.tcl, mh.tcl, msg.tcl, # # Revision 1.19 2002/07/16 01:27:54 sysphrog # Fixing problems with PGP sign+encrypt, gnupg 1.0.7 support # # Revision 1.18 2002/05/01 02:24:07 welch # A whole collection of patches. If marked with ** then I've lost # track of who gave them to me and I apologize for that: # exmh-strip.MASTER: added pref initialization to quiet errors caused # by changes elsewhere in the main body of exmh # install.tcl: fixed errors that occur when you try to display a # dialog box (e.g., the Verify window) that is already displayed # lib/addr.tcl: a new set of options for configuring LDAP (Mark Bergman) # lib/extrasInit.tcl: help text updates about the uquoteAdd resource (**) # lib/faces.tcl: fix for space-in-pathname problem (**) # lib/fcache.tcl: New Feature! display the count of unseen messages # in the folder cache. (Paul Menage) # lib/html_get_http.tcl: trap errors from bad http: links # lib/inc.tcl: tweaked feedback about inc'ed messages to do case-insensitive # grep for Subject: (**) # lib/mime.tcl: for for space-in-pathname problem # lib/pgpExec.tcl: eliminated Exmh_Debug message that could dump out # a massive keyring to the log, taking many many seconds (**) # lib/unseenwin.tcl: fix to tolerate space-in-folder-name (I think) (**) # # Revision 1.17 2001/12/08 00:39:52 kchrist # Fixed "GPG silently ignores untrusted keys during encryption" bug. # Thanks to Ben Escoto. # # Revision 1.16 2001/12/06 16:39:13 kchrist # Exmh can now parse the GnuPG options file and identify the # "default-key" (same as "myname" in PGP). Added "--status-fd 2" to # args_decrypt so that the output can be parsed with Pgp_InterpretOutput. # # Revision 1.15 2000/09/21 15:06:44 valdis # Catch PGP stderr so 'Get key' and 'Generate Key' work... # # Revision 1.14 2000/06/16 18:16:26 valdis # Various PGP fixes... # # Revision 1.13 2000/06/15 17:03:11 valdis # Add X-Mailer: change, fix PGP Comment: line... # # Revision 1.12 2000/04/18 18:38:33 valdis # Fix quote character to use ascii rather than iso8859-ish one # # Revision 1.11 1999/09/27 23:18:45 kchrist # More PGP changes. Consolidated passphrase entry to sedit field or # pgpExec routine. Made the pgp-sedit field aware of pgp(keeppass) # and pgp(echopass). Moved pgp(keeppass), pgp(echopass) and # pgp(grabfocus) to PGP General Interface. Fixed a minor bug left # over from my previous GUI changes. Made pgp-sedit field appear and # disappear based on its enable preference setting. # # Revision 1.10 1999/09/22 16:36:44 kchrist # Changes made to support a different structure under the PGP Crypt... button. # Instead of an ON/OFF pgp($v,sign) variable now we use it to specify # the form of the signature (none, standard, detached, clear, or w/encrypt). # Code changed in several places to support this new variable definition. # # Updated Sedit.html to include a description of the new interface. # # Revision 1.9 1999/08/22 18:57:36 bmah # Sanitize PGP debugging entries before writing via Exmh_Debug. # # Revision 1.8 1999/08/13 00:39:05 bmah # Fix a number of key/passphrase management problems: pgpsedit now # manages PGP versions, keys, and passphrases on a per-window # basis. Decryption now works when no passphrases are cached. # One timeout parameter controls passphrases for all PGP # versions. seditpgp UI slightly modified. # # Revision 1.7 1999/08/04 22:43:39 cwg # Got passphrase timeout to work yet again # # Revision 1.6 1999/08/04 16:30:17 cwg # Don't prompt for a passphrase when we shouldn't. # # Revision 1.5 1999/08/03 04:05:54 bmah # Merge support for PGP2/PGP5/GPG from multipgp branch. # # Revision 1.4.2.1 1999/06/14 20:05:15 gruber # updated multipgp interface # # Revision 1.4 1999/06/10 16:59:18 cwg # Re-enabled the timeout of PGP passwords # # Revision 1.3 1999/05/04 06:35:38 cwg # Fixed crash when aborting out of PGP Password window # # Revision 1.2 1999/04/10 04:20:08 cwg # Do the right thing if pgp(seditpgp) is not enabled. # # Revision 1.1 1998/05/05 17:55:37 welch # Initial revision # # Revision 1.1 1998/05/05 17:42:59 welch # Initial revision # # Revision 1.11 1998/01/22 00:45:06 bwelch # Hack to use aixterm for PGP. # # Revision 1.10 1997/12/22 20:52:00 bwelch # file delete # # Revision 1.9 1997/07/25 17:13:23 bwelch # Fixed pattern match to handle PGP 5.0 date format. # # Revision 1.8 1997/07/12 23:05:12 bwelch # Fixed PGP key extraction from the web servers. # Fixed handling of failed signatures so you still see the message. # # Revision 1.7 1997/06/03 18:29:55 bwelch # Added PGP grab-focus and use-expecttk options. # Removed +keepbinary=off flag from PGP uses. # PGP bin directory is added to the front of PATH, if necessary # # Revision 1.6 1997/01/25 05:29:23 bwelch # Tweaked PgpExec_KeyList that returns a list of keys. # Tweaked patterns on PGP output. # Added Pgp_ShortenOutput # # Revision 1.5 1996/12/21 00:57:12 bwelch # Log errors from PGP key extraction # # Revision 1.4 1996/12/01 20:13:59 bwelch # Added Pgp_InterpretOutput # Added timeouts on password caching. # # Revision 1.3 1996/03/22 18:42:54 bwelch # Added Mh_Rename # . # # Revision 1.2 1995/05/24 05:58:04 bwelch # Updates from Stefan # # Revision 1.1 1995/05/19 17:36:16 bwelch # Initial revision # # Revision 1.2 1995/03/22 19:14:21 welch # More new code from Stefan # # Revision 1.1 1994/12/30 21:49:00 welch # Initial revision # # Revision 1.1 1994/12/17 20:19:16 monnier # Initial revision # # execs pgp with the usual flags proc Pgp_Exec { v exectype arglist outvar {privatekey {}} {interactive 0} } { global pgp env upvar $outvar output Exmh_Debug "Pgp_Exec $v $exectype $arglist $outvar $privatekey $interactive" if {![set pgp($v,enabled)]} { error "<[set pgp($v,fullName)]> isn't enabled" } set output {} if {![set pgp(keeppass)]} { Pgp_ClearPassword $v } # gnupg agent requested? then batch! if {[set pgp(gpg,useagent)]} { Exmh_Debug " Pgp_Exec_Batch $v $exectype $arglist output" return [Pgp_Exec_Batch $v $exectype $arglist output] } else { if {$interactive || !([set pgp(keeppass)] || ($privatekey == {}))} { Exmh_Debug " Pgp_Exec_Interactive $v $exectype $arglist output" return [Pgp_Exec_Interactive $v $exectype $arglist output] } else { if {$privatekey == {}} { Exmh_Debug " Pgp_Exec_Batch $v $exectype $arglist output" return [Pgp_Exec_Batch $v $exectype $arglist output] } else { Exmh_Debug v=$v set keyid [lindex $privatekey 0] Exmh_Debug keyid=$keyid # Check for passphrase. Pgp_GetPass is cache and expire aware! set p [Pgp_GetPass $v $privatekey] #Exmh_Debug " got passwd >$p<" if {[string length $p] == 0} { return 0 } Exmh_Debug " Pgp_Exec_Batch $v $exectype $arglist output \(password\)" return [Pgp_Exec_Batch $v $exectype $arglist output $p] } } } } # batch mode proc Pgp_Exec_Batch { v exectype arglist outvar {password {}} } { global pgp exmh errorCode upvar $outvar output Exmh_Debug "Pgp_Exec_Batch $v $exectype $arglist $outvar \(password\)" set tclcmd [concat exec [set pgp($v,executable,$exectype)] \ [subst [set pgp($v,flags_batch)]] $arglist] Exmh_Debug " $tclcmd" # Set file descriptor for passphrase on stdin if {$password == {}} { Pgp_${v}_PassFdUnset } else { lappend tclcmd << $password Pgp_${v}_PassFdSet } set result [catch {eval $tclcmd |& cat} output] Exmh_Debug ": Exit status: $result $errorCode" # Unset file descriptor for passphrase Pgp_${v}_PassFdUnset regsub -all "\x07" $output "" output return $result } # interactive mode proc Pgp_Exec_Interactive { v exectype arglist outvar } { global tcl_platform pgp upvar $outvar output Exmh_Debug "Pgp_Exec_Interactive $v $exectype $arglist $outvar" set pgpcmd [set pgp($v,executable,$exectype)] set args [concat [subst [set pgp($v,flags_interactive)]] $arglist] # Be sure, that passphrase isn't read from stdin Pgp_${v}_PassFdUnset # Build shellcommand set shcmd " $pgpcmd \"[join [Pgp_Misc_Map x { regsub {([$\"\`])} $x {\\1} x set dummy $x } $args] {" "}]\"; echo echo press Return...; read dummy" set logfile [Mime_TempFile "xterm"] if { ( $tcl_platform(os) == "AIX" ) && [ file executable "/usr/bin/X11/aixterm" ] } { set xterm "aixterm" } else { set xterm "xterm" } # Hint: XFree86 xterm does not support output logging (Markus) # -l and -lf not supported set tclcmd {exec $xterm -l -lf $logfile -title [set pgp($v,fullName)] -e sh -c $shcmd} Exmh_Debug " $tclcmd" set result [catch $tclcmd] if [catch {open $logfile r} log] { set output {} } else { set output [read $log] close $log } eval [set pgp($v,cmd_cleanOutput)] return $result } proc Pgp_Exec_CheckPassword { v password key } { global pgp Exmh_Debug "Pgp_Exec_CheckPassword $v \(password\) $key" set in [Mime_TempFile "pwdin"] set out [Mime_TempFile "pwdout"] set filio [open $in w 0600] puts $filio "salut" close $filio set keyid [lindex $key 0] Pgp_Exec_Batch $v sign [subst [set pgp($v,args_signClear)]] err $password File_Delete $in # pgp thinks he knows better how to name files ! if {![file exists $out] && [file exists "$out.asc"]} { Mh_Rename "$out.asc" $out } if {![file exists $out]} { if [regexp [set pgp($v,pat_checkError)] $err x match] { Exmh_Status ?${match}? } Exmh_Debug " $err" return 0 } else { File_Delete $out return 1 } } # returns a list of keys. Each "key" is a list whose first four elements are # keyid algo subkeyid algo # and the next ones are the corresponding userids # {keyid algo subkeyid algo userid userid userid ...} proc Pgp_Exec_KeyList { v pattern keyringtype } { global pgp Exmh_Debug "Pgp_Exec_Keylist $v $pattern $keyringtype" set pattern [string trimleft $pattern "<>|2"] set arglist [subst [set pgp($v,args_list$keyringtype)]] ldelete arglist {} Pgp_Exec_Batch $v key $arglist keylist Exmh_Debug ": $keylist" # drop revoked and noninteresting keys regsub -all [set pgp($v,pat_dropKeys)] $keylist {} keylist # Form a list of keys regsub -all [set pgp($v,pat_splitKeys)] $keylist \x81 keylist set keylist [split $keylist \x81] # This print statement converts keylist from a Tcl list to # a string. For really big keylists, this is reportedly very expensive # Exmh_Debug ": Splitted keylist: $keylist" # Match out interesting keys set keypattern [set pgp($v,pat_key$keyringtype)] # subkeyparsing if [info exists pgp($v,pat_key${keyringtype}_sub)] { set subkeypattern [set pgp($v,pat_key${keyringtype}_sub)] } # uid parsing set uidpattern [set pgp($v,pat_uid)] # grep keys set AllowedToFollow 0 set keys {} foreach line $keylist { catch {unset userid} catch {unset keyid} set goodline 0 # if {[eval [set pgp($v,cmd_keyMatch)]]} { if {[info exists userids] && [info exists keyids]} { if {[llength $keyids] < 4} { lappend keyids {} {} } lappend keys [concat $keyids $userids] unset keyids unset userids } lappend keyids "0x$keyid" $algo catch {lappend userids $userid} set AllowedToFollow 1 set goodline 1 } if [info exists subkeypattern] { if {[eval [set pgp($v,cmd_keyMatch_sub)]] && $AllowedToFollow} { lappend keyids "0x$keyid" $algo set goodline 1 } } if {[eval [set pgp($v,cmd_uidMatch)]] && $AllowedToFollow} { lappend userids $userid set goodline 1 } if {!$goodline} { set AllowedToFollow 0 } } if {[info exists userids] && [info exists keyids]} { if {[llength $keyids] < 4} { lappend keyids {} {} } lappend keys [concat $keyids $userids] } # keys is of the format { {keyid algo subkeyid algo userid userid} {} {}...} return $keys } # parse config file # this is only needed to set pgp($v,myname) proc Pgp_Exec_ParseConfigTxt { v file } { global pgp Exmh_Debug "Pgp_Exec_ParseConfigTxt $file" if [catch {open $file r} in] { return } if {$v != "gpg"} { set pat "^\[ \t]*(\[a-z]+)\[ \t]*=(\[^#]*)" } else { # GnuPG uses space as separator and options may have dashes set pat "^\[ \t]*(\[a-z-]+)\[ \t]*(\[^#]*)" } for {set len [gets $in line]} {$len >= 0} {set len [gets $in line]} { if [regexp -nocase $pat $line {} option value] { set pgp($v,config,[string tolower $option]) [string trim $value " \t\""] } } close $in } ############### # Encrypt/Sign proc Pgp_Exec_Encrypt { v in out tokeys } { global pgp Exmh_Debug "Pgp_Exec_Encrypt $v $in $out $tokeys" Pgp_Exec_Batch $v encrypt [subst [set pgp($v,args_encrypt)]] output if {[Pgp_Exec_CheckSuccess $v $out $output "encrypted text"]} { # pgp refuses to generate an encrypted message # if a key was untrusted # interactively proceed catch {file delete $out} Pgp_Exec_Interactive $v encrypt [subst [set pgp($v,args_encrypt)]] output Pgp_Exec_CheckSuccess $v $out $output "encrypted text" } } proc Pgp_Exec_EncryptSign { v in out sigkey tokeys } { global pgp Exmh_Debug "Pgp_Exec_EncryptSign $v $in $out $tokeys" set keyid [lindex $sigkey 0] Pgp_Exec $v encrypt [subst [set pgp($v,args_encryptSign)]] output $sigkey if {[Pgp_Exec_CheckSuccess $v $out $output "signed and encrypted text"]} { # pgp refuses to generate an encrypted/signed message # if a key was untrusted # interactively proceed catch {file delete $out} Pgp_Exec $v encrypt [subst [set pgp($v,args_encryptSign)]] output $sigkey 1 Pgp_Exec_CheckSuccess $v $out $output "signed and encrypted text" } } proc Pgp_Exec_Sign { v in out sigkey opt } { global pgp Exmh_Debug "Pgp_Exec_Sign $v $in $out $sigkey $opt" set keyid [lindex $sigkey 0] switch $opt { standard {Pgp_Exec $v sign [subst [set pgp($v,args_signBinary)]] output $sigkey} detached {Pgp_Exec $v sign [subst [set pgp($v,args_signDetached)]] output $sigkey} clearsign {Pgp_Exec $v sign [subst [set pgp($v,args_signClear)]] output $sigkey} default {set output "Pgp_Exec_Sign error. Unknown option."} } Pgp_Exec_CheckSuccess $v $out $output "signed text" } # Look if pgp generated pgp code proc Pgp_Exec_CheckSuccess {v out output object} { global pgp Exmh_Debug "Pgp_Exec_CheckSuccess $v $out $output $object" # pgp thinks he knows better how to name files ! if {![file exists $out] && [file exists "$out.asc"]} { Mh_Rename "$out.asc" $out } if {$v != "gpg"} { # pgp5 refuses to generate ciphertext in batchmode # if tokey is untrusted if {![file exists $out]} { if {[regexp [set pgp($v,pat_Untrusted)] $output]} { return 1 } else { error "[set pgp($v,fullName)] refused to generate the ${object}:\n$output" } } else { return 0 } } else { # GnuPG will also not encrypt to a key if it is untrusted but if # any of the encryption keys are trusted a file will be generated if {[regexp "^(.*\n)*gpg:.*no (info|indication)" $output]} { return 1 } else { return 0 } } } ################# # Decrypt/Verify # get the key to use for decryption proc Pgp_Exec_GetDecryptKey {v in recipients} { global pgp Exmh_Debug "Pgp_Exec_GetDecryptKey $v $in $recipients" # If the user has time (this doesn't consume more than a half second) # and has set preferences to run pgp twice, # run pgp a first time to get out the decryption keyid set runtwice 0 if {[info exists pgp($v,runtwice)] && [set pgp($v,runtwice)]} { set runtwice 1 } if {$runtwice} { Exmh_Debug " Pgp_Exec_GetDecryptKeyid $v $in" set keyid [Pgp_Exec_GetDecryptKeyid $v $in] if {$keyid == {}} { return {} } elseif {[string match $keyid SYM]} { # SYMMETRIC ENCRYPTION set key [list SYM {} {} {} "symmetrically encrypted message"] } else { # One of user's private keys? If so, than use it. # make sure that we look at *all* subkeys foreach key [set pgp($v,privatekeys)] { for {set i 0} {$i<[expr [llength $key]-1]} {incr i 2} { if {[regexp $keyid [lindex $key $i]]} { return $key } } } return {} } } else { set recipients [string tolower $recipients] # Messages get encrypted with the subkey for dsa/elg # I don't know if there are subkeyids in the recipients list if dsa/elg # Lets search for mainkeys set useablekeys [Pgp_Misc_Filter key \ {[string first [string tolower [string range [lindex $key 0] 2 end]] $recipients] >= 0} \ [set pgp($v,privatekeys)]] # If no mainkeys were found, search for subkeys if {[llength $useablekeys] == 0} { set useablekeys [Pgp_Misc_Filter key \ {[string first [string tolower [string range [lindex $key 2] 2 end]] $recipients] >= 0} \ [set pgp($v,privatekeys)]] } set knownkeys [Pgp_Misc_Filter key \ {[info exists pgp($v,pass,[lindex $key 0])]} $useablekeys] if {[llength $knownkeys] > 0} { set key [lindex $knownkeys 0] } elseif {[llength $useablekeys] > 0} { set key [lindex $useablekeys 0] } else { set key {} } } return $key } proc Pgp_Exec_GetDecryptKeyid {v in} { global pgp Exmh_Debug "Pgp_Exec_GetDecryptKeyid $v $in" Pgp_Exec_Batch $v verify [subst [set pgp($v,args_getDecryptKeyid)]] output if {[regexp [set pgp($v,pat_getDecryptKeyid)] $output {} keyid]} { } elseif {[regexp [set pgp($v,pat_getDecryptSym)] $output]} { set keyid SYM } else { Exmh_Debug " No key matches" return {} } Exmh_Debug " keyid $keyid" return $keyid } proc Pgp_Exec_Decrypt { v in out outvar recipients } { global pgp upvar $outvar output Exmh_Debug "Pgp_Exec_Decrypt $v $in $out $outvar $recipients" set key [Pgp_Exec_GetDecryptKey $v $in $recipients] Exmh_Debug " $key" Pgp_Exec $v verify [subst [set pgp($v,args_decrypt)]] output $key } proc Pgp_Exec_Verify { v in outvar {out {}}} { upvar $outvar output global pgp Exmh_Debug "Pgp_Exec_Verify $v $in $outvar $out" if {$out == {}} { Exmh_Debug ": Pgp_Exec_Verify $v $in $outvar $out" Pgp_Exec $v verify [subst [set pgp($v,args_verifyOnly)]] output } else { Exmh_Debug ": Pgp_Exec_Verify $v $in $outvar $out" Pgp_Exec $v verify [subst [set pgp($v,args_verifyOut)]] output } } proc Pgp_Exec_VerifyDetached { v sig text outvar } { upvar $outvar output global pgp Exmh_Debug "Pgp_Exec_VerifyDetached $v $sig $text $outvar" Pgp_Exec $v verify [subst [set pgp($v,args_verifyDetached)]] output } ################## # NOT WITH GNUPG # # This is called if expectk is enabled. It seemed the best (easiest # for me) way to do it was to have this proc terminate when the # message is finished displaying just as Exec_Decrypt would do. # However, this is a problem for the the expectk script # (PgpDecryptExpect), which may need to communicate with exmh to ask # for passwords, etc. # My slow and inelegant solution was to tell exmh-bg all the necessary # information and let PgpDecryptExpect communicate with exmh-bg, # exiting when done. # proc Pgp_Exec_DecryptExpect { v infile outfile msgvar } { global exmh exwin sedit pgp upvar $msgvar msg # First update exmh-bg arrays. I hope that pgp, getpass, # and exwin will be enough. For exwin seems we have # to temporarily change the mtext error to avoid an error when # the password window is closed and focus is returned to .msg.t send $exmh(bgInterp) [list array set pgp [array get pgp]] send $exmh(bgInterp) [list array set getpass [array get getpass]] send $exmh(bgInterp) [list array set sedit [array get sedit]] send $exmh(bgInterp) [list array set exwin [array get exwin]] send $exmh(bgInterp) [list set exwin(mtext) .] if [catch {exec $exmh(expectk) -f $exmh(library)/PgpDecryptExpect \ $v $infile $outfile $exmh(bgInterp)} error] { Exmh_Debug " error: $error" Exmh_Status "Error executing expect process" warn } set msg [lindex [send $exmh(bgInterp) {list $pgpmsg}] 0] send $exmh(bgInterp) [list unset pgpmsg] # Now reload pass and exwin from exmh-bg foreach index [send $exmh(bgInterp) [list array names pgp $v,pass,*]] { set pgp($index) [send $exmh(bgInterp) [list set pgp($index)]] send $exmh(bgInterp) [list unset pgp($index)] } # The following appears no longer to be necessary, but now I don't see # how to change the position of the getpass window # # set exwin(geometry,.getpass) \ # [send $exmh(bgInterp) list {$exwin(geometry,.getpass)}] } #################### proc Pgp_Exec_ExtractKeys { v file outvar {interactive 1} } { global env pgp upvar $outvar output Exmh_Debug "Pgp_Exec_ExtractKeys $v $file $outvar $interactive" set output {} if [Pgp_Exec $v key [subst [set pgp($v,args_importKey)]] output {} $interactive] { Exmh_Status "Key extract failed" Exmh_Debug " $output" return 0 } else { Exmh_Debug " $output" return 1 } } # Get the passphrase for keyinstance key. We also take care of setting # passphrase timeouts. Return a stored passphrase when possible. proc Pgp_GetPass { v key } { global pgp if {[info exists pgp(extpass)] && [set pgp(extpass)] \ && [info exists pgp(getextcmd)]} { Exmh_Debug "Pgp_GetPass $v $key external" set keyid [lindex $key 0] set cmd [format $pgp(getextcmd) $keyid] while (1) { Exmh_Debug "running cmd $cmd" if [ catch {exec sh -c "$cmd"} result ] { Exmh_Debug "error running cmd: $result" Exmh_Status "Error executing external cmd" warn return {} } else { if {[Pgp_Exec_CheckPassword $v $result $key]} { return $result } else { Exmh_Debug "bad passphrase" if {[info exists pgp(delextcmd)]} { Exmh_Debug "trying to invalidate bad passphrase" if [catch {exec sh -c "[format $pgp(delextcmd) $keyid]"}] { Exmh_Debug "invalidation failed" return {} } } } } } } else { Exmh_Debug "Pgp_GetPass $v $key" if {[lsearch -glob [set pgp($v,privatekeys)] "[lindex $key 0]*"] < 0} { return {} } # Search the passphrase "cache". Need to set-timeout here in case # the pass phrase was created via the seditpgp entry field. # Because of DecryptExpects asymmetric passphrase storage # we need to look for both mainkey and subkey separately set keyid [lindex $key 0] set subkeyid [lindex $key 2] if {([info exists pgp($v,pass,$keyid)]) && \ ([string length $pgp($v,pass,$keyid)] > 0)} { Pgp_SetPassTimeout $v $keyid if {[string length $subkeyid] > 0} { Pgp_SetPassTimeout $v $subkeyid } return [set pgp($v,pass,$keyid)] } elseif {([string length $subkeyid] > 0) && \ ([info exists pgp($v,pass,$subkeyid)]) && \ ([string length $pgp($v,pass,$subkeyid)] > 0)} { Pgp_SetPassTimeout $v $subkeyid return [set pgp($v,pass,$subkeyid)] } # Not in "cache" (or expired) go ask for it. while 1 { Exmh_Debug "Attempt to get passphrase for [lindex $key 0] [lindex $key 1] [lindex $key 4]" if [catch {Pgp_Misc_GetPass $v "Enter [set pgp($v,fullName)] passphrase" \ "Passphrase for [lindex $key 0] [lindex $key 1] [lindex $key 4]"} password] { return {} } elseif {[string match $keyid SYM]} { # SYMMETRIC ENCRYPTION return $password } elseif {[Pgp_Exec_CheckPassword $v $password $key]} { if [set pgp(keeppass)] { set pgp($v,pass,$keyid) $password Pgp_SetPassTimeout $v $keyid # Because of DecryptExpect we need to store passphrase # for mainkey and subkey if {[string length $subkeyid] > 0} { set pgp($v,pass,$subkeyid) $password Pgp_SetPassTimeout $v $subkeyid } } return $password } } } } proc Pgp_SetPassTimeout {v keyid} { global pgp if [info exists pgp(timeout,$keyid)] { Exmh_Debug "Cancelling previous timeout for $keyid" after cancel $pgp(timeout,$keyid) unset pgp(timeout,$keyid) } Exmh_Debug "Setting timeout for $keyid ($v) in $pgp(passtimeout) minutes" set pgp(timeout,$keyid) \ [after [expr $pgp(passtimeout) * 60 * 1000] \ [list Pgp_ClearPassword $v $keyid]] } # wipe password away proc Pgp_ClearPassword { v {keyid {}} } { global pgp if {[string length $keyid] == 0} { foreach index [array names pgp $v,pass*] { Exmh_Debug "Clearing pgp($index)" set pgp($index) {} } set pgp($v,pass,) {} } else { catch {Exmh_Debug "Clearing only pgp($v,pass,$keyid)"} catch {set pgp($v,pass,$keyid) {}} } } proc Pgp_Exec_GetKeys { v keyid file } { global pgp Exmh_Debug "Pgp_Exec_GetKeys $v $keyid $file" set arglist [subst [set pgp($v,args_exportKey)]] ldelete arglist {} if [Pgp_Exec $v key $arglist msg] { error $msg } else { Pgp_Exec_CheckSuccess $v $file $msg "key block for $keyid" } } # Shutdown Cleanup proc Pgp_CheckPoint {} { foreach cmd { Pgp_Match_CheckPoint } { if {[info command $cmd] != {}} { if [catch {$cmd} err] { puts stderr "$cmd: $err" } } } } ### Init ### proc Pgp_Exec_Init {} { global env pgp Pgp_SetPath # needed in pgpMatch if {![info exists env(LOCALHOST)]} { if [catch {exec uname -n} env(LOCALHOST)] { set env(LOCALHOST) localhost } } foreach v $pgp(supportedversions) { if {[set pgp($v,enabled)]} { set pgp($v,pass,) {} # Parse config file if { [set pgp($v,parse_config)] } { Pgp_Exec_ParseConfigTxt $v [set pgp($v,configFile)] } if {![file exists [set pgp($v,secring)]]} { set pgp($v,secring) {} } set pgp($v,privatekeys) [Pgp_Exec_KeyList $v $pgp($v,ownPattern) Sec] # GnuPG uses default-key for what PGP uses myname if {![info exists pgp($v,config,myname] && \ [info exists pgp($v,config,default-key)]} { set pgp($v,config,myname) $pgp($v,config,default-key) } # if [info exists pgp($v,config,myname)] { set myname [string tolower [set pgp($v,config,myname)]] foreach key [set pgp($v,privatekeys)] { if {[string first $myname [string tolower $key]] >= 0} { # pgp($v,myname) holds the default key to use # for each version of PGP. It will be used # to initialize pgp($v,myname,$id) in each # sedit window. set pgp($v,myname) $key break } } if {![info exists pgp($v,myname)]} { if [catch {Pgp_Match_Simple $v [set pgp($v,config,myname)] Sec} key] { tk_messageBox -type ok -icon warning \ -title "[set pgp($v,fullName)] Init" \ -message "The name specified in your [set pgp($v,fullName)] config file couldn't be unambiguously found in your key rings !" set pgp($v,myname) {} } else { set pgp($v,myname) $key } } } else { set pgp($v,myname) [lindex [set pgp($v,privatekeys)] 0] } } } } exmh-2.9.0/lib/flagdown.mask0000644000170700017070000000367413201227060015244 0ustar valdisvaldis#define icon-empty_m.bm_width 48 #define icon-empty_m.bm_height 48 #define icon-empty_m.bm_x_hot 0 #define icon-empty_m.bm_y_hot 0 static unsigned char icon-empty_m.bm_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x01, 0x00, 0xfc, 0xff, 0x7f, 0xff, 0x19, 0x00, 0xfc, 0xff, 0x0f, 0xff, 0xfd, 0x00, 0xfe, 0xff, 0x03, 0xff, 0xfd, 0x01, 0xfe, 0xff, 0x61, 0xff, 0xf9, 0x00, 0xfe, 0xff, 0xf9, 0xff, 0xfd, 0x01, 0xfe, 0xff, 0xf8, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0xfc, 0xff, 0x33, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x01, 0x00, 0xfc, 0x3f, 0x20, 0xff, 0x01, 0x00, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x00, 0xf0, 0x0f, 0x70, 0xff, 0x1d, 0x00, 0xe0, 0x03, 0xf0, 0xff, 0x09, 0x00, 0x00, 0x00, 0x30, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; exmh-2.9.0/lib/pgpBase.tcl0000644000170700017070000001550413201227060014646 0ustar valdisvaldis# pgpBase.tcl # # This file contains basic variables and procedures needed # for the initialisation process # # $Log$ # Revision 1.9 2009/01/08 02:51:23 az143 # gpg since version 1.2 uses "gpg.conf" as configfile, not "options" # # Revision 1.8 2003/05/20 03:43:30 welch # pgpPgp65.tcl added version check improvement for PGP 6.5 (Neil Rickert) # (added . - and _ to the pattern, too (kre)) # # Revision 1.7 2001/05/18 22:54:22 bmah # Made the PGP detection code actually try to execute a program # (e.g. "gpg --version") and parse the output to determine the presence # of installed PGP versions. Formerly, only the existence of files # was checked. # # For the most part, there shouldn't be any change, but this makes it easier # to support PGP6 under FreeBSD (the FreeBSD Ports Collection installs PGP # as /usr/local/bin/pgp). # # Revision 1.6 2000/06/16 18:16:26 valdis # Various PGP fixes... # # Revision 1.5 2000/06/09 03:46:25 valdis # PGP 6.5 support # # Revision 1.4 1999/08/24 15:51:07 bmah # Patch from Kevin Christian to make email PGP key queries work, and # to make key attachment RFC 2015 compliant. # # Revision 1.3 1999/08/22 18:17:08 bmah # Email PGP queries now go out correctly. Use Exmh_Status to inform # user of state of an outgoing email key query. # # Revision 1.2 1999/08/03 04:05:54 bmah # Merge support for PGP2/PGP5/GPG from multipgp branch. # # Revision 1.1.4.3 1999/07/18 12:52:04 gruber # *** empty log message *** # # Revision 1.1.4.2 1999/07/09 12:36:10 gruber # few fixes # # Revision 1.1.4.1 1999/06/14 20:05:14 gruber # updated multipgp interface # # Revision 1.1 1999/06/14 15:14:53 markus # added files # proc Pgp_Base_Init {} { global pgp miscRE env ### # ---- For all versions ---- # set miscRE(headerend) {^(--+.*--+)?$} set miscRE(mimeheaders) {^content-[-a-z]+:} set miscRE(true) {^(on|y(es)?|t(rue)?)$} set miscRE(beginpgp) {^-+BEGIN PGP} set miscRE(beginpgpkeys) {^-+BEGIN PGP PUBLIC KEY BLOCK-+$} set miscRE(beginpgpclear) {^-+BEGIN PGP SIGNED MESSAGE-+$} set pgp(enabled) 0 set pgp(pat_MenuInner) {Pgp} set pgp(supportedversions) [list pgp pgp5 gpg pgp6] # -- GnuPG -- # set pgp(gpg,enabled) 0 set pgp(gpg,fullName) "GnuPG" set pgp(gpg,executable,key) gpg set pgp(gpg,executable,verify) gpg set pgp(gpg,executable,encrypt) gpg set pgp(gpg,executable,sign) gpg set pgp(gpg,executable,version) gpg set pgp(gpg,executable,versionflags) "--version" set pgp(gpg,executable,versionregexp) "^gpg" if [info exists env(GNUPGHOME)] { set pgp(gpg,defaultPath) "$env(GNUPGHOME)" } else { set pgp(gpg,defaultPath) "$env(HOME)/.gnupg" } set pgp(gpg,configFile) "$pgp(gpg,defaultPath)/gpg.conf" set pgp(gpg,pubring) "$pgp(gpg,defaultPath)/pubring.gpg" set pgp(gpg,secring) "$pgp(gpg,defaultPath)/secring.gpg" set pgp(gpg,pubringBkp) "$pgp(gpg,defaultPath)/pubring.gpg~" set pgp(gpg,keyGenCmd) "rm -f $pgp(gpg,pubringBkp) && gpg --gen-key" set pgp(gpg,ownPattern) "" ## ButtonMenuInner set pgp(gpg,pat_MenuInner) {GPG} ## Version checking and Compatibilty set pgp(gpg,pat_Version) "Version:\[ \t\]*(GNUPG|GnuPG).*" set pgp(gpg,list_Alien) {pgp5 pgp6 pgp} # -- PGP 2.6 -- # set pgp(pgp,enabled) 0 set pgp(pgp,fullName) "PGP 2.6" set pgp(pgp,executable,key) pgp set pgp(pgp,executable,verify) pgp set pgp(pgp,executable,encrypt) pgp set pgp(pgp,executable,sign) pgp set pgp(pgp,executable,version) pgp set pgp(pgp,executable,versionflags) "-v" set pgp(pgp,executable,versionregexp) "^Pretty Good Privacy.* 2\." if [info exists env(PGPPATH)] { set pgp(pgp,defaultPath) "$env(PGPPATH)" } else { set pgp(pgp,defaultPath) "$env(HOME)/.pgp" } set pgp(pgp,configFile) "$pgp(pgp,defaultPath)/config.txt" set pgp(pgp,pubring) "$pgp(pgp,defaultPath)/pubring.pgp" set pgp(pgp,secring) "$pgp(pgp,defaultPath)/secring.pgp" set pgp(pgp,pubringBkp) "$pgp(pgp,defaultPath)/pubring.bak" set pgp(pgp,keyGenCmd) "rm -f $pgp(pgp,pubringBkp) && pgp -kg" set pgp(pgp,afterKeyGen) { if {![file exists pgp(pgp,pubringBkp)]} { return } else { set tmpfile [Mime_TempFile "pgp"] Exec_GetKeys pgp \ [lindex [lindex $pgp(pgp,privatekeys) 0] 0] $tmpfile Pgp_Misc_Send $pgp(pgp,keyserver) ADD $tmpfile \ "content-type: application/pgp; format=keys-only" File_Delete $tmpfile } } set pgp(pgp,ownPattern) "" ## ButtonMenuInner set pgp(pgp,pat_MenuInner) {PGP[^5]} ## Version checking and Compatibilty set pgp(pgp,pat_Version) "Version:\[ \t\]*2\.6.*" set pgp(pgp,list_Alien) {pgp5 pgp6 gpg} # -- PGP 5.0 -- # set pgp(pgp5,enabled) 0 set pgp(pgp5,fullName) "PGP 5.0" set pgp(pgp5,executable,key) pgpk set pgp(pgp5,executable,verify) pgpv set pgp(pgp5,executable,encrypt) pgpe set pgp(pgp5,executable,sign) pgps set pgp(pgp5,executable,version) pgpv set pgp(pgp5,executable,versionflags) "--version" set pgp(pgp5,executable,versionregexp) "^PGP.* unix5" set pgp(pgp5,defaultPath) "$pgp(pgp,defaultPath)" set pgp(pgp5,configFile) "$pgp(pgp5,defaultPath)/pgp.cfg" set pgp(pgp5,pubring) "$pgp(pgp5,defaultPath)/pubring.pkr" set pgp(pgp5,secring) "$pgp(pgp5,defaultPath)/secring.skr" set pgp(pgp5,pubringBkp) "$pgp(pgp5,defaultPath)/pubring.bak" set pgp(pgp5,keyGenCmd) "rm -f $pgp(pgp5,pubringBkp) && pgpk -g" set pgp(pgp5,ownPattern) "" ## ButtonMenuInner set pgp(pgp5,pat_MenuInner) {PGP5} ## Version checking and Compatibilty set pgp(pgp5,pat_Version) "Version:\[ \t\]*((PGP\[^\n\]*)? 5\\.|PGPsdk).*" set pgp(pgp5,list_Alien) {gpg pgp pgp6} # -- PGP 6.5.n -- # set pgp(pgp6,enabled) 0 set pgp(pgp6,fullName) "PGP 6.5" set pgp(pgp6,executable,key) pgp6 set pgp(pgp6,executable,verify) pgp6 set pgp(pgp6,executable,encrypt) pgp6 set pgp(pgp6,executable,sign) pgp6 set pgp(pgp6,executable,version) pgp6 set pgp(pgp6,executable,versionflags) "-v" set pgp(pgp6,executable,versionregexp) "^Pretty Good Privacy.* 6" if [info exists env(PGPPATH)] { set pgp(pgp6,defaultPath) "$env(PGPPATH)" } else { set pgp(pgp6,defaultPath) "$env(HOME)/.pgp" } set pgp(pgp6,configFile) "$pgp(pgp6,defaultPath)/config.txt" set pgp(pgp6,pubring) "$pgp(pgp6,defaultPath)/pubring.pkr" set pgp(pgp6,secring) "$pgp(pgp6,defaultPath)/secring.skr" set pgp(pgp6,pubringBkp) "$pgp(pgp6,defaultPath)/pubring-bak-1.pkr" set pgp(pgp6,keyGenCmd) "rm -f $pgp(pgp6,pubringBkp) && pgp6 -kg" set pgp(pgp6,afterKeyGen) { if {![file exists pgp(pgp6,pubringBkp)]} { return } else { set tmpfile [Mime_TempFile "pgp"] Exec_GetKeys pgp \ [lindex [lindex $pgp(pgp6,privatekeys) 0] 0] $tmpfile Pgp_Misc_Send $pgp(pgp6,keyserver) ADD $tmpfile \ "content-type: application/pgp; format=keys-only" File_Delete $tmpfile } } # this is somewhat bogus, but seems to work... set pgp(pgp6,ownPattern) "." ## ButtonMenuInner set pgp(pgp6,pat_MenuInner) {PGP6} ## Version checking and Compatibilty set pgp(pgp6,pat_Version) "Version:\[ \t-._A-Za-z\]*6\.5.*" set pgp(pgp6,list_Alien) {pgp pgp5 gpg} ### } exmh-2.9.0/lib/html_get_http.tcl0000644000170700017070000003334013201227060016125 0ustar valdisvaldis# fetch a url via a proxy server. The Cern proxy server appears to # handle http, ftp, wais, and gopher. # url: The name of the url to fetch # command The command to run when the fetch is complete # progress A progress call-back to provide status information # it gets called with 3 args: # This is the default global state array set Http [list \ hunk 1024 \ max_pending 5 \ pending "" \ agent "SunLab's Tcl/Tk Editor $WebTk(version)" \ queue {} \ ] # only accept these types (This is usually ignored) set Http(accept) { text/plain text/html image/gif image/jpeg image/xbm } proc Http_SetProxy {win} { global Http DialogEntry $win .proxy " Enter host name and port of your Http proxy server. If you do not use a proxy server, clear the server field. " HttpSetProxyOK [list [list server $Http(server)] [list port $Http(port)]] } proc HttpSetProxyOK {list} { global Http array set Http $list CheckPoint } proc HttpAgent {} { global Http return $Http(agent) } proc Http_CheckPoint {out} { global Http puts $out [list array set Http [list \ server $Http(server) \ port $Http(port) \ ]] } proc Http_get {url {command #} {progress #}} { upvar #0 $url data set data(protocol) GET catch {unset data(query)} regexp {\?(.+)} $url x data(query) HttpGet $url $command $progress } # POST to ship form data proc Http_post {url query {command {}} {progress {}}} { global Http upvar #0 $url data set data(query) $query set data(protocol) POST HttpGet $url $command $progress } # Use HEAD to just validate a URL. proc Http_head {url {command {}}} { upvar #0 $url data set data(protocol) HEAD HttpGet $url $command } proc HttpGet {url {command #} {progress #}} { global Http upvar #0 $url data if {![info exists data(count)]} { set data(count) 0 } if {![info exists data(url)] || [info exists data(query)] || ($data(protocol) != "HEAD" && $data(count) == 0 && \ ([lsearch $Http(queue) $url] < 0) && ([lsearch $Http(pending) $url] < 0))} { set data(url) $url set data(state) queued ;# internal state set data(requests) 1 ;# number of times requested set data(count) 0 ;# bytes retrieved so far set data(length) 0 ;# expected size (bytes) catch {unset data(html)} ;# Nuke old page lappend data(command) $command ;# command to run on completion set data(progress) $progress ;# progress callback lappend Http(queue) $url after idle Http_poke } else { incr data(requests) if {$data(state) == "done"} { HttpLog fetching existing url ($command) catch $command } elseif {$data(state) == "link"} { HttpLog fetching linked url ($data(link)) Http_get $data(link) $command } else { HttpLog appending ($command) to ($data(command)) lappend data(command) $command } } catch {eval $progress $data(state) $data(count) $data(length)} if [info exists data(state)] { return $data(state) } else { return {} } } # process an item on the Url Queue. This gets automatically rescheduled # when a fetch is complete. proc Http_poke {} { global Http HttpHost if {$Http(queue) == ""} { return 0 } if {[llength $Http(pending)] >= $Http(max_pending)} { after 2000 Http_poke return 0 } # find the item on the head of the Q set url [lindex $Http(queue) 0] set Http(queue) [lrange $Http(queue) 1 end] lappend Http(pending) $url upvar #0 $url data # go ask for the url, and wait for the data set data(state) connecting set data(what) connect set port {} if ![regexp -nocase {(http|ftp)://([^/:]+)(:([0-9]+))?(.*)} $url x protocol host y port srvurl] { HttpLog Invalid url $url Http_kill $url return } if {[string length $port] == 0} { set port 80 } if {$protocol == "http"} { # Callback to determine if a proxy is necessary lassign [Http_Proxy $host] proxy pport if [catch { if [string length $proxy] { set sock [HttpConnect $proxy $pport $data(protocol) $url] } else { set sock [HttpConnect $host $port $data(protocol) $srvurl] } } err] { HttpLog $err Http_kill $url return } } elseif {$protocol == "ftp"} { if [catch {set sock [FtpConnect $host 21]} err] { HttpLog $err Http_kill $url return } } else { HttpLog "Unsupported URL: $url" Http_kill $url return } set data(socket) $sock set data(mime) {} set data(what) connected if {$protocol == "http" && [catch { foreach type $Http(accept) { puts $sock "Accept: $type" } puts $sock "User-Agent: [HttpAgent]" puts $sock "Host: $host" if {$data(protocol) == "POST"} { HttpLog $data(query) puts $sock "Content-type: application/x-www-form-urlencoded" puts $sock "Content-length: [string length $data(query)]\n" puts $sock "$data(query)" puts $sock "\n" } else { puts $sock "" } flush $sock # Our translation is now lf because of our own output. Reset it. fileevent $sock r [list Http_event $url] fconfigure $sock -translation auto } err]} { # Connect really failed. HttpLog $err Http_kill $url return } elseif {$protocol == "ftp"} { global ftp set ftp(cmdSock) $sock if {![FtpSetConnectionInfo $url]} { HttpLog "invalid URL for FTP: $url" Http_kill $url return } fileevent $sock r [list Ftp_event $url] } catch {eval $data(progress) connecting 0 0} return 1 } proc HttpConnect {server port cmd url} { HttpLog $server:$port $cmd $url HTTP/1.0 set sock [socket $server $port] fconfigure $sock -blocking false puts $sock "$cmd $url HTTP/1.0" flush $sock return $sock } # got fileevent for this URL # data(what) determines the current fetching state # connected The first line is about to be received # header Getting the mime header # body getting the message body # file getting the body into a file # error no mime header, put entire text into message # This doesn't work for Pre HTTP/1.0 servers. if {[info commands "unsupported0"] == "unsupported0"} { rename unsupported0 copychannel } if {[info commands "copychannel"] == ""} { proc copychannel {in out {size {}}} { if {$size == ""} { return [fcopy $in $out] } else { return [fcopy $in $out -size $size] } } } proc Http_event {url} { global Http upvar #0 $url data if {![info exists data] || ![info exists data(socket)]} { return } if ![info exists data(count)] { set data(count) 0 } set more 1 switch $data(what) { connect - connecting - connected { set more [HttpGetLine $data(socket) line] HttpLog $line <$url> if {[regexp {^HTTP/1\.[01] *(.*)} $line dummy data(http)]} { set data(what) header } else { if {[regexp {([^:]+):[ ]*(.*)} $line dummy key value]} { set data(what) header HttpHeader $url $key $value } elseif {[regexp {<|>} $line]} { # Looks like error document with no protocol header. set data(http) "400 Error" set data(html) $line set data(what) body } else { set data(message) $line set data(html) {} set data(what) error } } } error { if [catch {read $data(socket) $Http(hunk)} block] { catch {eval $data(progress) error $more 0} HttpLog "Read error on $url\n$block" Http_kill $url return } set more [string length $block] if {$more > 0} { append data(message) $block incr data(count) $more catch {eval $data(progress) error $data(count) $data(length)} } } header { set more [HttpGetLine $data(socket) line] if {$line == ""} { if {[info exists data(file)]} { # Divert remaining data into a file. # Turn off cr-lf translations to preserve all bits. set data(what) file fconfigure $data(socket) -translation lf } else { fconfigure $data(socket) -translation auto set data(what) body } return } if {![regexp {([^ :]+):[ ]*(.*)} $line dummy key value]} { return } HttpHeader $url $key $value return } body { if [catch {read $data(socket) $Http(hunk)} block] { catch {eval $data(progress) error $more 0} HttpLog "Read error on $url\n$block" Http_kill $url return } set more [string length $block] if {$more > 0 } { append data(html) $block incr data(count) $more catch {eval $data(progress) body $data(count) $data(length)} } } file { if [catch {copychannel $data(socket) $data(fd) $Http(hunk)} more] { HttpLog "Read error on $url\n$more" catch {eval $data(progress) error $more 0} Http_kill $url return } if {$more >= 0} { incr data(count) $more catch {eval $data(progress) file $data(count) $data(length)} } } } if {[info exists data(socket)] && [eof $data(socket)]} { catch {close $data(socket)} Http_depend $url unset data(socket) set data(state) done if {$data(what) == "file"} { catch {close $data(fd)} unset data(fd) Cache_SetFile $url $data(file) } catch {eval $data(progress) done $data(count) $data(length)} foreach cmd $data(command) { HttpLog $cmd catch $cmd } set data(command) "" after idle Http_poke return 1 } } proc HttpHeader {url key value} { upvar #0 $url data regsub "\r" $value {} value lappend data(mime) $key $value switch [string tolower $key] { content-length { set data(length) $value } location { UrlResolve $url value HttpLog "linking to $value" set data(link) $value set data(state) link catch {close $data(socket)} unset data(socket) Http_depend $url foreach i $data(command) { Http_get $value $i $data(progress) } set data(command) "" catch {eval $data(progress) linking $value 0} set data(progress) "" return } content-type { set data(type) $value if [regexp text/plain $value] { set data(html) {} } elseif {![regexp {text/html} $value]} { set data(file) [Cache_NewFile $data(url)] if {[catch {open $data(file) w 0600} data(fd)]} { Exmh_Status "Cannot write to HTML cache directory" Http_kill $data(url) } else { HttpLog "using file $data(file)" fconfigure $data(fd) -translation lf } } } } } # remove a url from the pending list proc Http_depend {url} { global Http if {[set index [lsearch -exact $Http(pending) $url]] >=0} { set Http(pending) [lreplace $Http(pending) $index $index] return 1 } else { return 0 } } # stop fetching a url proc Http_kill {url} { global Http upvar #0 $url data if {[info exists data(socket)]} { catch {close $data(socket)} unset data(socket) Http_depend $url set data(state) killed after idle Http_poke } elseif {[set pos [lsearch -exact $Http(queue) $url]] >=0} { lreplace $Http(queue) $pos $pos } else { Http_depend $url } catch { set data(valid) complete ;# nudge tkwaiters unset data } } proc Http_stop {} { global Http foreach url [concat $Http(pending) $Http(queue)] { Http_kill $url } } proc HttpGetLine {sock lineVar} { upvar $lineVar line set line {} if [catch {gets $sock line} n] { HttpLog $sock $n return 0 } return $n } proc HttpTrace {} { global Http trace variable Http(queue) w HttpTraceQueue trace variable Http(pending) w HttpTracePending set Http(listbox) .httpbox set f $Http(listbox) if ![winfo exists $f] { toplevel $f wm group $f . wm title $f "HTTP Queue" wm iconname $f "HTTP Queue" label $f.label -text "HTTP Queue" button $f.quit -text "Dismiss" -command {destroy .httpbox} label $f.status -text "(status line)" -textvar Http(dbg_status) label $f.lqueue -text Queue label $f.lpending -text Active listbox $f.queue listbox $f.pending set Http(log) [text $f.log -width 50 -height 10 -wrap none \ -yscrollcommand "$f.yscroll set" \ -xscrollcommand "$f.xscroll set"] scrollbar $f.xscroll -command "$f.log xview" -orient horiz scrollbar $f.yscroll -command "$f.log yview" -orient vert bind $f.queue {HttpTraceInfo queue %y} bind $f.pending {HttpTraceInfo pending %y} bind $f.queue {HttpTraceKill queue %y} bind $f.pending {HttpTraceKill pending %y} grid $f.quit $f.label - grid $f.status - - -sticky news grid $f.lqueue $f.lpending -sticky news grid $f.queue $f.pending -sticky news grid $f.log - $f.yscroll -sticky news grid $f.xscroll - -sticky news grid columnconfigure $f 0 -weight 1 grid columnconfigure $f 1 -weight 1 grid columnconfigure $f 2 -weight 0 grid rowconfigure $f 2 -weight 1 grid rowconfigure $f 3 -weight 1 grid $f.label -sticky news grid $f.quit -sticky w } HttpTraceQueue HttpTracePending } proc HttpLog {args} { global Http catch { $Http(log) insert end [join $args { }]\n $Http(log) see end } } proc HttpTraceQueue {args} { global Http catch { $Http(listbox).queue delete 0 end foreach f $Http(queue) { $Http(listbox).queue insert end $f } } } proc HttpTraceKill {what y} { global Http set list $Http(listbox).$what set i [$list cur] if {[string length $i]} { Http_kill [$list get $i] } } proc HttpTraceInfo {what y} { global Http set list $Http(listbox).$what set i [$list nearest $y] set Http(dbg_status) {} catch {trace vdelete $Http(dbg_url) w HttpTraceTrace} if {[string length $i]} { set url [$list get $i] global $url upvar #0 $url data trace variable $url w HttpTraceTrace HttpTraceTrace $url } } proc HttpTraceTrace {name1 args} { global Http upvar #0 $name1 data set Http(dbg_status) {} foreach key {state what count length http} { if [info exists data($key)] { append Http(dbg_status) "$key=\"$data($key)\" " } } update idletasks } proc HttpTracePending {args} { global Http catch { $Http(listbox).pending delete 0 end foreach f $Http(pending) { $Http(listbox).pending insert end $f } } } exmh-2.9.0/lib/flag.tcl0000644000170700017070000001254513201227060014200 0ustar valdisvaldis# # flag.tcl # # Manage the iconic flag feedback. The flag module understands three states, # but the icon only shows two states: # # State 0 - no unseen messages. # State 1 - newly arrived unseen messages. # State 2 - messages viewed while in State 1, but not necessarily all unseen # messages viewed yet. # # The mailbox flag goes up on the transition to State 1 (from either State 0 # or State 2), and the flag goes down on the transition to State 2. So, # it is possible to have the flag down and still have unseen messages. The # idea is that the flag means new mail has arrived since you last looked # at *something*. # # Copyright (c) 1993 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. proc Flag_Init {} { global flag exmh flist mhProfile set flag(state) init # Note - if you change the icon, there is some code in ExmhArgv # that positions icons that can depend on the iconsize. Preferences_Resource flag(iconup) iconUpBitmap flagup.bitmap Preferences_Resource flag(icondown) iconDownBitmap flagdown.bitmap Preferences_Resource flag(iconspool) iconSpoolBitmap flagspool.bitmap Preferences_Resource flag(labelup) iconUpLabel {$flist(totalcount,$mhProfile(unseen-sequence)) Unseen} Preferences_Resource flag(labeldown) iconDownLabel exmh Preferences_Resource flag(labelspool) iconSpoolLabel {$exmh(numUnInced) Spooled} Preferences_Resource flag(iconupmask) iconUpMask flagup.mask Preferences_Resource flag(icondownmask) iconDownMask flagdown.mask Preferences_Resource flag(iconspoolmask) iconSpoolMask flagspool.mask Preferences_Resource flag(iconupglyph) iconUpGlyph flagup.gif Preferences_Resource flag(icondownglyph) iconDownGlyph flagdown.gif Preferences_Resource flag(iconspoolglyph) iconSpoolGlyph flagspool.gif foreach i {iconup icondown iconspool iconupmask icondownmask iconspoolmask iconupglyph icondownglyph iconspoolglyph} { if ![string match /* $flag($i)] { set flag($i) $exmh(library)/$flag($i) } if ![file exists $flag($i)] { set flag($i) 0 } } if {$exmh(slowDispColorIcon)} { if [catch { Exmh_Debug "Creating .icon" toplevel .icon wm group .icon . pack [canvas .icon.c] image create photo icondown -file $flag(icondownglyph) image create photo iconup -file $flag(iconupglyph) image create photo iconspool -file $flag(iconspoolglyph) .icon.c configure -width [image width iconup] \ -height [image height iconup] wm iconwindow . .icon } err] { Exmh_Debug "Can't create .icon: $err" destroy .icon } } FlagInner down icondown labeldown trace variable flist(totalcount,$mhProfile(unseen-sequence)) wu Flag_Trace } proc Flag_Trace args { global flist mhProfile if {[info exists flist(oldtotalcount,$mhProfile(unseen-sequence))]} { set oldtotal $flist(oldtotalcount,$mhProfile(unseen-sequence)) } else { set oldtotal 0 } if {[info exists flist(totalcount,$mhProfile(unseen-sequence))]} { set newtotal $flist(totalcount,$mhProfile(unseen-sequence)) } else { set newtotal 0 } Exmh_Debug Flag_Trace oldtotal $oldtotal newtotal $newtotal set delta [expr {$newtotal - $oldtotal}] set flist(oldtotalcount,$mhProfile(unseen-sequence)) $newtotal if {($delta > 0) && ($newtotal > 0)} { set count $newtotal if {$count == 1} {set m ""} else {set m "s"} set len [llength $flist($mhProfile(unseen-sequence))] if {$len == 1} {set f ""} else {set f "s"} Exmh_Status "$count unseen message$m in $len folder$f" Flag_NewMail Sound_Feedback $delta } if {($newtotal <= 0) && ($delta != 0)} { Flag_NoUnseen Exmh_Status "No unseen messages" } } proc Flag_NewMail { {folder {}} } { FlagInner up iconup labelup } # Flag_MsgSeen drops the flag but retains the proper label # This is called after viewing a message proc Flag_MsgSeen { {folder {}} } { global flist mhProfile if {[info exists flist(totalcount,$mhProfile(unseen-sequence))] && $flist(totalcount,$mhProfile(unseen-sequence)) > 0} { FlagInner spool iconspool labelup } else { FlagInner down icondown labeldown } } proc Flag_NoUnseen {} { FlagInner down icondown labeldown } proc Flag_Spooled {} { FlagInner spool iconspool labelspool } proc Flag_NoSpooled {} { FlagInner down icondown labeldown } proc FlagInner {state icon label} { global exmh flag # Exmh_Debug "In FlagInner $state $icon $label" if {$flag(state) != $state} { if [winfo exists .icon.c] { # Exmh_Debug "Setting flag glyph to $icon" .icon.c delete image -tag icon .icon.c create image 0 0 -anchor nw -image $icon -tag icon } else { # Exmh_Debug "Setting flag bitmap to $icon" wm iconbitmap . @$flag($icon) if {$flag(${icon}mask) != 0} { wm iconmask . @$flag(${icon}mask) } } set flag(state) $state # Exmh_Debug "Set flag state to $state" } set l [uplevel #0 list $flag($label)] if {[info exists flag(lastLabel)] && ([string compare $l $flag(lastLabel)] == 0)} { return } wm title . $l wm iconname . $l set flag(lastLabel) $l } exmh-2.9.0/lib/html_content.tcl0000644000170700017070000000306513201227060015762 0ustar valdisvaldis# content.tcl # Handlers for different content types called by UrlDisplay. # These procedures need to return 1 or 0. # A 1 indicates they displayed something in the current page. # If they can't do anything with the content, they should raise an error # and UrlDisplay will call the next content type handler. proc Content_text/html {win url} { upvar #0 HM$win var upvar #0 $url data regsub {\?.*} $url {} var(S_url) Url_DisplayHtml $win $var(S_url) $data(html) return 1 } proc Content_text/plain {win url} { upvar #0 HM$win var upvar #0 $url data set var(S_url) $url HMreset_win $win wm title [winfo toplevel $win] [file tail $url] wm iconname [winfo toplevel $win] [file tail $url] $win insert 1.0 $data(html) return 1 } proc Content_image {win url} { upvar #0 $url data Status $win "starting xv to view image" exec xv $data(file) & return 0 } proc Content_default {win url} { upvar #0 HM$win var upvar #0 $url data if [info exists data(message)] { regsub {\?.*} $url {} var(S_url) Url_DisplayHtml $win $var(S_url) $data(message) return 1 } else { if {[info exists data(file)] && [file exists $data(file)]} { set localname \ [FSBox "Location for downloaded file" "" write] while {$localname != {}} { if [catch { file copy -- $data(file) $localname } err] { Status $win $err } else { Status $win "Saved to $localname" break } set localname \ [fileselect "Location for downloaded file"] } catch {rm -f $data(file)} } return 0 } } exmh-2.9.0/lib/html_dpackage.tcl0000644000170700017070000007712213201227060016054 0ustar valdisvaldis# Simple HTML display library by Stephen Uhler (stephen.uhler@sun.com) # Copyright (c) 1995 by Sun Microsystems # Version 0.3 Thu Aug 31 14:11:29 PDT 1995 # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # To use this package, create a text widget (say, .text) # and set a variable full of html, (say $html), and issue: # HMinit_win .text # HMparse_html $html "HMrender .text" # You also need to supply the routine: # proc HMlink_callback {win href} { ...} # win: The name of the text widget # href The name of the link # which will be called anytime the user "clicks" on a link. # The supplied version just prints the link to stdout. # In addition, if you wish to use embedded images, you will need to write # proc HMset_image {handle src} # handle an arbitrary handle (not really) # src The name of the image # Which calls # HMgot_image $handle $image # with the TK image. # # To return a "used" text widget to its initialized state, call: # HMreset_win .text # See "sample.tcl" for sample usage ################################################################## ############################################ # mapping of html tags to text tag properties # properties beginning with "T" map directly to text tags # These are Defined in HTML 2.0 array set HMtag_map { address {style i} b {weight bold} big {size 5} blockquote {indent 1 Trindent rindent} bq {indent 1 Trindent rindent} cite {style i} code {size 3 family courier} dfn {style i} dir {indent 1} dl {indent 1} em {style i} h1 {size 6 weight bold Tspace hspacebig family times} h2 {size 5 weight bold Tspace hspacebig family times} h3 {size 4 weight bold Tspace hspacemid family times} h4 {size 3 weight bold Tspace hspacemid family times} h5 {size 2 weight bold Tspace hspacemid family times} h6 {size 1 Tspace hspacesml family times} i {style i} kbd {family courier weight bold} menu {indent 1} ol {indent 1} pre {fill 0 family courier size 3 Tnowrap nowrap} samp {size 3 family courier} small {size 2} strong {weight bold} sup {size 2 Tsup sup} sub {size 2 Tsup sub} tt {size 3 family courier} u {Tunderline underline} ul {indent 1} var {style i} } # This correspond to the Netscape font sizes 1 to 7 array set HMsize_map { "" "" 1 10 2 12 3 14 4 18 5 20 6 24 7 36 } # These are in common(?) use, but not defined in html2.0 array set HMtag_map { center {Tcenter center} strike {Tstrike strike} u {Tunderline underline} } # initial values set HMtag_map(hmstart) { family times weight medium style r size 3 Tcenter "" Tlink "" Tnowrap "" Tunderline "" list list fill 1 indent "" counter 0 adjust 0 Tspace hspacep } proc HMdefault_font {win} { upvar #0 HM$win var global HMsize_map HMx_font times $HMsize_map(3) medium r $var(S_adjust_size) } ############################################ # initialize the window and stack state proc HMinit_win {win} { global window upvar #0 HM$win var HMinit_state $win $win tag configure underline -underline 1 $win tag configure center -justify center $win tag configure left -justify left $win tag configure right -justify right $win tag configure nowrap -wrap none $win tag configure rindent -rmargin $var(S_tab)c $win tag configure strike -overstrike 1 $win tag configure mark -foreground red ;# list markers if {$window(colorAnchor)} { $win tag configure anchor -foreground purple } $win tag configure HTML -foreground #880 -background #d9d9d9 $win tag configure SHTML -foreground #800 -background #d9d9d9 \ -relief ridge -borderwidth 2 # Restore foreground/background 'cause tag can change it. $win config -background [lindex [$win config -background] 3] $win config -foreground [lindex [$win config -foreground] 3] $win tag configure hspacebig -spacing1 10p -spacing3 6p $win tag configure hspacemid -spacing1 6p -spacing3 3p $win tag configure hspacesml -spacing1 3p -spacing3 3p $win tag configure hspacep -spacing1 3p -spacing3 3p $win tag configure compact -spacing1 1p -spacing3 0p $win tag configure abovebr -spacing3 0p $win tag configure belowbr -spacing1 0p $win tag configure sup -offset 3 ;# superscript $win tag configure sub -offset -3 ;# subscript $win tag bind link [list Url_Hit? $win %x %y] $win tag bind link [list Url_HitNew $win %x %y] $win tag bind link [list Url_Edit $win %x %y] HMset_indent $win $var(S_tab) $win configure -wrap word # configure the text insertion point $win mark set $var(S_insert) 1.0 # for horizontal rules Hr_Init $win bind $win { %W tag configure last -spacing3 %h } if {0} { # These are already on the exmh window bind TScroll {%W yview scroll 1 page} bind TScroll {%W yview scroll -1 page} bind TScroll {%W see 1.0} bind TScroll {%W see end} } } # set the indent spacing (in cm) for lists # TK uses a "weird" tabbing model that causes \t to insert a single # space if the current line position is past the tab setting proc HMset_indent {win cm} { $win configure -tabs [expr $cm / 2.0]c foreach i {1 2 3 4 5 6 7 8 9} { set indent [expr $i * $cm] $win tag configure indent$i -lmargin1 ${indent}c -lmargin2 ${indent}c \ -tabs "[expr $indent + $cm/2.0]c [expr $indent + $cm]c" \ -rmargin ${cm}c } } # reset the state of window - get ready for the next page # remove all but the font tags, and remove all form state proc HMreset_win {win {clear 1}} { upvar #0 HM$win var if $clear { eval $win mark unset [$win mark names] $win delete 0.0 end # configure the text insertion point $win mark set $var(S_insert) 1.0 } $win tag configure hr -tabs [winfo width $win] Head_ResetColors $win Form_Reset $win catch {Table_Reset $win} Image_Reset $win HMinit_state $win return HM$win } # initialize the window's state array # Parameters beginning with S_ are NOT reset # adjust_size: global font size adjuster # unknown: character to use for unknown entities # tab: tab stop (in cm) # stop: enabled to stop processing # update: how many tags between update calls # tags: number of tags processed so far # symbols: Symbols to use on un-ordered lists proc HMinit_state {win} { upvar #0 HM$win var array set tmp [array get var S_*] catch {unset var} array set var { stop 0 tags 0 fill 0 list list listtags "" S_adjust_size 0 S_tab 1.0 S_unknown \xb7 S_update 10 S_symbols O*=+-o\xd7\xb0>:\xb7 S_insert Insert } array set var [array get tmp] } # alter the parameters of the text state # this allows an application to over-ride the default settings # it is called as: HMset_state -param value -param value ... array set HMparam_map { -update S_update -tab S_tab -unknown S_unknown -stop stop -size S_adjust_size -symbols S_symbols -insert S_insert } proc HMset_state {win args} { upvar #0 HM$win var global HMparam_map set bad 0 if {[catch {array set params $args}]} {return 0} foreach i [array names params] { incr bad [catch {set var($HMparam_map($i)) $params($i)}] } return [expr $bad == 0] } ############################################ # manage the display of html # HMrender gets called for every html tag # win: The name of the text widget to render into # tag: The html tag (in arbitrary case) # not: a "/" or the empty string # param: The un-interpreted parameter list # text: The plain text until the next html tag proc HMrender {win tag not param text} { global HMtag_map BreakMap upvar #0 HM$win var if {$var(stop)} return set tag [string tolower $tag] set text [HMmap_esc $text] incr var(tags) ;# Counter used for UID's # Divert table contents if [info exists var(tableHandler)] { if [catch {eval $var(tableHandler) {$tag $not $param text}} err] { Stderr $err } return } # adjust (push or pop) tag state catch {HMstack$not $win $HMtag_map($tag)} # to fill or not to fill set fill [lindex $var(fill) end] if $fill { set text [HMzap_white $text] } # Break the line, if necessary if [info exists BreakMap($tag)] { if $fill { set text [string trimleft $text] } if ![info exists var(newline)] { dputs "newline" Text_Insert $win $var(S_insert) \n "space $var(listtags)" set var(newline) 1 set var(trimspace) 1 catch {unset var(Tbr)} ;# br hack } } # generic mark hook to support the editor if [catch {HMmark $win $tag $not $param text} err] { dputs "HMmark $err" } # do any special tag processing if [catch {HMtag_$not$tag $win $param text} msg] { if {[info command HMtag_$not$tag] != {}} { ;# dputs global errorInfo ;# dputs Exmh_Debug "HMtag_$not$tag: $errorInfo" ;# dputs } ;# dputs } if {$fill && [info exists var(trimspace)]} { set text [string trimleft $text] } if {[string compare $text ""] != 0} { catch {unset var(trimspace)} catch {unset var(newline)} } # HMcurrent_tags has side effects. Call even if text is empty set tags [HMcurrent_tags $win] # Fix here to do something better with   which is \0xa0 Text_Insert $win $var(S_insert) $text $tags # We need to do an update every so often to insure interactive response. # This can cause us to re-enter the event loop, and cause recursive # invocations of HMrender, so we need to be careful. if {!($var(tags) % $var(S_update))} { update } } # html tags requiring special processing # Procs of the form HMtag_ or HMtag_ get called just before # the text for this tag is displayed. These procs are called inside a # "catch" so it is OK to fail. # win: The name of the text widget to render into # param: The un-interpreted parameter list # text: A pass-by-reference name of the plain text until the next html tag # Tag commands may change this to affect what text will be inserted # next. # A pair of pseudo tags are added automatically as the 1st and last html # tags in the document. The default is and . # Append enough blank space at the end of the text widget while # rendering so HMgoto can place the target near the top of the page, # then remove the extra space when done rendering. proc !HMtag_hmstart {win param text} { upvar #0 HM$win var $win mark gravity $var(S_insert) left $win insert end "\n " last $win mark gravity $var(S_insert) right } proc !HMtag_/hmstart {win param text} { $win delete last.first end } # put the document title in the window banner, and remove the title text # from the document proc !HMtag_title {win param text} { upvar $text data dputs $data wm title [winfo toplevel $win] $data wm iconname [winfo toplevel $win] $data set data "" } # remove blocks we don't know how to interpret anyhow. Thanks to Don Koch for the patch, and Rick Baartman for asking. cvs repository 05/08/2005 valdis.kletnieks@vt.edu exmh.l: debian bug #309891 by way of Alexander Zangerl Fix a bunch of typos cvs repository 4/27/2005 jbeck@eng.sun.com lib/app-defaults-color lib/msgShow.tcl: Added support for marking text between stars (e.g., I *really* mean it) in a bold font. cvs repository 4/27/2005 jbeck@eng.sun.com lib/app-defaults-color lib/msgShow.tcl: Updated regular expressions for Sun bug report highlighting, added support for SpamAssassin report highlighting. cvs repository 4/27/2005 welch@panasas.com lib/bogo.tcl: Added BogoSetup as a trace on bogo(progname) so that preference changes are reflected immediately w/out restarting exmh. cvs repository 4/21/2005 valdis.kletnieks@vt.edu lib/mime.tcl: Add call to FileExistsDialog to prompt before saving a MIME part into an already existing file. cvs repository 4/15/2005 welch@panasas.com channeling Alexander Zangerl lib/bogo.tcl: add the option to give the spam filter a list of message file names on its command line instead of running the filter once on each message as standard input. We know this works for spamassassin, but not sure about the other filters. cvs repository 4/4/2005 welch@panasas.com lib/fileselect.tcl: made use of the built-in tk file dialogs optional. The setting is under the "FS Box" preferences panel. my fingers have grown to know and love the fileselect behavior. lib/fileselect.tcl lib/html_content.tcl lib/main.tcl lib/mime.tcl lib/msg.tcl lib/seditExtras.tcl Restored/updated calls to FSbox (aka fileselect) lib/flist.tcl: fixed FlistUncache to properly clear the global variable in the bg interp lib/mh.tcl: added calls to FlistUncache cvs repository 3/18/2005 welch@panasas.com channeling Alexander Zangerl lib/flist.tcl: Adding FlistUncache to unset flistcache when appropriate lib/folder.tcl: Call FlistUncache when we commit folder changes cvs repository 3/17/2005 welch@panasas.com channeling Alexander Zangerl exmhcomp: support mailto URLs cvs repository 3/4/2005 cwg-exmh@deepeddy.com lib/seqwin.tcl - Make Warp & Narrow work if you aren't already in the folder. cvs repository 3/1/2005 cwg-exmh@deepeddy.com lib/html_content.tcl, lib/main.tcl, lib/mime.tcl, lib/msg.tcl, lib/seditExtras.tcl - Call tk_getOpenDialog or tk_GetSaveDialog instead of FSBox. cvs repository 3/1/2005 cwg-exmh@deepeddy.com lib/main.tcl: Add 'Source' button to log window so I can read in a new source file w/o erasing what's in the command line. cvs repository 3/1/2005 cwg-exmh@deepeddy.com lib/flist.tcl: Run FlistUnseenFoldersInit in the foreground so that it actually works. cvs repository 2/18/2005 cwg-exmh@deepeddy.com lib/ftoc.tcl: Fix patch of 2/3 so it doesn't break if you don't have a detached message window. cvs repository 2/9/2005 valdis.kletnieks@vt.edu lib/mime.tcl: resolve (or at least work around) Debian bug 294212 as a too-zealous splatting of specials broke some content types. I'm adding '.' to the list, but I'm not comfortable adding the full list of rc2045 chars as it includes some shell metachars... cvs repository 2/3/2005 cwg-exmh@deepeddy.com lib/ftoc.tcl: Reset exwin(ftext) whenever the ftext window changes size. cvs repository 1/25/2005 cwg-exmh@deepeddy.com lib/mime.tcl: Special case display of original message in spamassassin processed mail so it doesn't display by default. cvs repository 1/24/2005 welch@panasas.com lib/folder.tcl: fixed the background folder purging script to properly pick up things from the script library cvs repository 1/19/2005 cwg-exmh@deepeddy.com lib/ftoc.tcl: Really fixed bindings for exwin(ftext). cvs repository 1/18/2005 cwg-exmh@deepeddy.com lib/exwin.tcl: Fixed bindings for exwin(ftext). cvs repository 1/17/2005 welch@panasas.com lib/seditExtras.tcl: fixed exmh-async variation of ispell command. lib/seditSel.tcl: fixed exmh-async variation of ispell command cvs repository 1/12/2005 welch@panasas.com lib/uri.tcl: changed use of "file link" back to exec ln lib/quote.tcl: changed use of "file link" back to exec ln exmh-strip.MASTER: eliminated use of [glob ~/.exmh/tk] in the setting of exmh(userLibrary), which we shouldn't need lib/mime.tcl: fix the exec of exmh-strip to be ${argv0}-strip to handle installations with a different base name. Makefile: fixed the ftpdist production cvs tag exmh-2-7-2 cvs repository 1/7/2005 welch@panasas.com lib/exwin.tcl: fixed up lingering focus and position issues with the detached message and ftoc windows. I also trimmed out all the sedit and pref windows from the saved window positions in the case that the window is "stale". lib/msgShow.tcl: added call to Exwin_SeeToplevelMsg in case the user has withdrawn the message display exmh-strip.MASTER: cleared out the Exmh_Debug messages that leak to standard output lib/mime.tcl: added dialog to Save/Extract attachments if the file already exists. exmh.install: changed 2.7.2 date to 1/7/2005 cvs repository 1/6/2005 welch@panasas.com lib/seqwin.tcl: Fixed a buglet that caused the incorrect display (missing the first folder) in the sequences window in some cases. lib/sequences.tcl: removed some erroneous debugging code. once again I forgot that catch will trap a "return", not just errors lib/mh.tcl: minor clean up - changed "catch {set foo}" to "info exists foo" lib/main.tcl: added logging to the startup sequence exmh.install: changed 2.7.2 date to 1/6/2005 cvs repository 1/6/2005 valdis.kletnieks@vt.edu lib/fdisp.tcl - enable scrollwheel support for fdisp canvas cvs repository 1/5/2005 welch@panasas.com lib/folderNew.tcl: folder-protect value wasn't being interpreted as octal when creating new folders. exmh.install: bumped version date cvs repository 1/5/2005 valdis.kletnieks@vt.edu lib/fileselect.tcl, lib/seditExtras.tcl patch from George Ross to not smash filenames when attaching a file to a message, only when saving an attachment cvs repository 1/4/2005 welch@panasas.com exmh-strip.MASTER: Added stub for "winfo" so I could run this with tclsh instead of wish. Updated comments. Made the search for filename hints more aggresive. Added exit if the output file already exists. Added some safety checking on the file name lib/app-defaults: Eliminated " " from the {Save "From" addr} menu entry because it looks like that entry raises errors sometimes. cvs repository 1/4/2005 welch@panasas.com lib/mime.tcl: fixed handling of non-existent attachement save directory cvs repository 1/3/2005 welch@panasas.com lib/html/software.html: updated links cvs repository 1/3/2005 welch@panasas.com added misc/mafe, as contributed by Andrew Billyard which is a perl-tk editor for mh aliases files. cvs repository 1/3/2005 welch@panasas.com Makefile: exmh.README: exmh.install: version.sed: lib/html/index.html lib/html/software.html changed version to 2.7.2 version.csh: Added comments lib/html/exmh.README.html: Added notes about 2.7.2 cvs repository 1/3/2005 welch@panasas.com lib/exwin.tcl: Fixed packing bug for ftoc window that means it didn't match the ftext lines preference setting. cvs repository 1/2/2005 welch@panasas.com lib/app-defaults: added "Save/Extract Attachments" that calls Mime_SaveAttachments. lib/mime.tcl: Added Mime_SaveAttachements that uses exmh-strip to pull an attachment out of an email message. There is a new preference item under "Mime" where you specify the default location for the resulting files. The default is ~/attachments. cvs repository 1/1/2005 welch@panasas.com (for Alexander Zangerl) lib/pgpGpg.tcl: lib/pgpPgp5.tcl: fix of an old pgp problem where recipients were duplicated when pgp is run in interactive mode lib/extrasInit.tcl: a small documentation improvement for the pgp(getextcmd) functionality. faces(xfaceProg) gains a default (uncompface -X) lib/pgpExec.tcl: fix for http://bugs.debian.org/164210: multiple gpg subkeys and passphrases. exmh would not ask for the right passphrase. lib/addr.tcl: ldap options gain defaults that are compatible with debian's openldap config lib/mh.tcl: add Msg-Protect and Folder-Protect to the default .mh_profile that is generated when setting up new users. (These changes are inspired by a patch from Alexander, but not the same) lib/inc.tcl: use $install(dir,bin) to specify an absolute path to the inc.expect script lib/seditExtras.tcl: use $install(dir,bin) to specify an absolute path to the exmh-async script lib/mime.tcl: use $install(dir,bin) to specify an absolute path to the ftp.expect script. Also changed MimeMakeBoundary to use [clock seconds] instead of re-writing the output of [exec date]. cvs repository 12/31/2004 welch@panasas.com lib/exwin.tcl: removed code that explicitly set ftoc and msg window heights that had been added as part of the detatched msg and ftoc changes. This isn't necessary and causes misinterpretation of the preferences ftoc lines value. (reportedly, this change doesn't fix anything.) cvs repository 12/29/2004 welch@panasas.com lib/mh.tcl: Optimized MhReadSeq to not loop through the mhPriv array in Tcl, but instead use the array command's ability to work on subsets of an array by using patters. This really speeds up Flist. NOTE: THIS DEPENDS ON A TCL 8.3 FEATURE FOR THE "array unset" COMMAND lib/flag.tcl: cleaned out some Exmh_Debug calls lib/folder.tcl: removed unnecessary calls to Seq_Msgs for sequences listed in the sequences resource. I can't figure out what good that was supposed to do. lib/sequences.tcl: Replaced Seq_Trace with SeqCount, and call it explicitly instead of from a trace. lib/seqwin.tcl: added error checking because it gets called earlier than before because of the explicit SeqCount calls lib/seditExtras.tcl: Also allow for "7bit" and "8bit" encodings. lib/utils.tcl: FileDelete adds a log message now cvs repository 10/18/2004 welch@panasas.com lib/seditExtras.tcl: patch from George Ross to fix attachments of plain files with no encoding. cvs repository 10/11/2004 welch@panasas.com lib/mime.tcl: lib/seditExtras.tcl exmh-strip.MASTER: added ability to use mimencode if it exists, because it is much faster than using the Tcl versions. We should also figure out how to use mhstore. lib/seditQP.tcl: minor edits lib/background.tcl: added better debugging for when the background process gets errors from commands shipped to the front end. lib/flist.tcl: restored the flistcache removed on 9/10 because the impact was substantial. There is still a buglet in there where the right sequence of message views, deletes, and arrivals can fool the cache. I think the correct thing is to special case the current folder, but I haven't done that yet. lib/inc.tcl: Introduced the use of Mh_FolderFast to set the current folder because "exec folder +foo" turns out to readdir() the entire folder, which can be a bit slow on horrendously large directories. lib/mh.tcl: fixed Mh_SetContext cvs repository 10/08/2004 valdis.kletnieks@vt.edu lib/base64.tcl - properly deal with trailing '=' so we don't append spurious nulls to the file cvs repository 10/08/2004 valdis.kletnieks@vt.edu lib/seditExtras.tcl - add fconfigure -translation binary so base64 encoding works properly. cvs repository 09/10/2004 welch@panasas.com lib/flist.tcl: removed the flistcache as inspired by Harvey Eneman and Jongki Suwandi. This cache caused message highlighting to not occur in some cases. lib/mh.tcl: patch from Harvey Eneman to fix the problem where Mh_Sequences does not clear the in-memory sequence state if a sequence file no longer exists. cvs repository 08/23/2004 welch@panasas.com lib/base64.tcl: fix two bugs, one with perfectly aligned blocks where there was an "undefined result" error. The other was that lines were not properly split at 72 chars. lib/mime.tcl: properly set binary encoding on decoded files. cvs repository 08/07/2004 valdis.kletnieks@vt.edu lib/app-defaults, lib/editor.tcl, lib/extrasInit.tcl, lib/mh.tcl, lib/sedit.tcl, lib/mh.tcl, lib/html/DSN-MDN.html, misc/README.nmh-dsn Oldie but goodie - merge in patch from Martin Hamilton to allow setting RFC3461 DSN options (originally against 1.6.5). Requires a patched mh/nmh (I forwarded the nmh guys a patch for nmh 1.1rc3 and put a patch for nmh 1.0.4 in misc/ for good measure). cvs repository 07/29/2004 welch@panasas.com lib/bogo.tcl - added Exmh_Status to Bogo_Filter because they take a while cvs repository 07/28/2004 welch@panasas.com lib/bogo.tcl - added catch around sa-learn pipe, as that can raise errors if sa-learn generates error output. lib/app-defaults - Added new key bindings Bogo_Filter spam Bogo_Filter ham lib/html_images.tcl lib/html.tcl - added preference to disable image display in a list of folder patterns. Contributed by Jürgen Vollmer lib/sequences.tcl - changed default for seqwin(show) to "unseen" from "cur" cvs repository 07/28/2004 valdis.kletnieks@vt.edu Clean up 2 bugs from the 07/26 'exec' hunt... lib/preferences.tcl - remove extraneous -p flag on 'file mkdir' lib/urlFace.tcl - missed an 'exec' call better done with regsub. cvs repository 07/26/2004 welch@panasas.com exmh-strip.MASTER: removed use of mime(encode) exmh.install: set version to 2.7.1 install.tcl: removed old unused global statement lib/base64.tcl: chopped Base64_Encode into three parts, Base64_EncodeInit, Base64_EncodeBlock, Base64_EncodeTail so it can be used more flexibly as a replacement for mimencode Changed Base64_Decode to tolerate and ignore newlines lib/exwin.tcl: got the non-detached window case to work for me. lib/main.tcl: changed the exmhDebug default to 0 because I was getting massive console spew lib/mime.tcl: removed use of mime(encode) lib/seditExtras.tcl: removed use of mime(encode). If you are a heavy user of the Quote feature in Sedit, you should check this as there is an auto-detect of quoted-printable in here that I support, but cannot see how it is ever reached. lib/seditQP.tcl: removed use of mime(encode) cvs repository 07/26/2004 welch@panasas.com lib/pick.tcl: Applied patch from Bruce Mah to search over sender or mailing-list headers lib/seqin.tcl: Applied patch from Axel Belinfante to be able to have sequences that are always shown, and those that are never shown. lib/sequences.tcl: Added preference for sequences to always show lib/utils.tcl Moved Axel's "mylsearch" into utils.tcl as "patsearch" cvs repository 07/26/2004 valdis.kletnieks@vt.edu catch CVS up to a weekend's worth of concentrated coding... Bayesian filter stuff... lib/bogo.tcl - Add support for spamassassin's sa-learn program lib/app-defaults - Add a menu for bogo.tcl calls, as the stuff in misc/README.mybogo.html is woefully out of date - in fact, it didn't handle a "range" of messages at all. The grey-out code for the Spam... menu is wonky - it *should* grey out if $bogo(inUse) is false, but that's too complicated for 3AM coding. Also, you can't learn a folder unless you first select a message. Adding key-S and key-H bindings also not done... If anybody cares enough, feel free to fix/improve/add it... :) lib/html/software.html - Mention spamassassin as an optional package lib/html/custom.html - Document the Preferences pane for bogo.tcl, and sort the list to match the actual display order of the entries. A few small clean-ups.. Doc fixups.. lib/html/exmh.README.html - fix a typo in Anders Klement's name, and cleaned up some broken HTML links/etc and outdated info (like an AIX 3.2 bug - if anybody's trying to install exmh on a 3.2 system, that's the least of their worries...) lib/report.tcl - DTRT if user has a personalized 'components' file, or a 'comp: -form some.other.comps' MH profile.. (very important if they have stuff like a From: header needed to make the mail actually usable...) lib/folder.tcl - Change a /tmp to [Env_Tmp] to stop races lib/utils.tcl - remove pre-TCL 8.0 code from File_Delete lib/mh.tcl - remove ancient tk4.2 code from Mh_Rename lib/folder.tcl, lib/glimpse.tcl, lib/pgpWWW.tcl, lib/scan.tcl, lib/seditExtras.tcl, lib/seditSel.tcl, lib/tioga.tcl, lib/urlFace.tcl, lib/folderNew.tcl, lib/getnews.tcl, lib/glimpse.tcl, lib/html_content.tcl, lib/html_cache.tcl, lib/html_images.tcl, lib/inc.tcl, lib/mime.tcl, lib/mh.tcl, lib/quote.tcl, lib/pgpMain.tcl, lib/preferences.tcl, lib/uri.tcl - replace 'exec chmod' with 'file attributes -permissions' replace 'exec mkdir' with 'file mkdir', 'exec ln' with 'file link', 'exec mv' with 'file rename', most 'exec cp' with 'file copy', 'exec rmdir' with 'file delete', mass change of 'exec rm' to either File_Delete or [file delete -force' cvs repository 07/18/2004 valdis.kletnieks@vt.edu lib/fileselect.tcl - Be more anal-retentive in what default names we will accept. Alphanumeric, period, hyphen, underscore only. Also, we trim off leading dots, just in case the user isn't paying attention... cvs repository 07/18/2004 valdis.kletnieks@vt.edu lib/mime.tcl - Same mail as below fix triggered another buglet - we should *always* prefer a rfc2183 Content-Disposition: filename= over a name= off the Content-Type: header. The code as written was dependent on what order we saw the MIME headers (blech!). While there, I also added a few filtering regsub calls... cvs repository 07/18/2004 valdis.kletnieks@vt.edu lib/mime.tcl - fix MimeSetDisplayFlag to properly implement rfc2183 Content-Disposition: precidence. Bug found when I got a image/jpeg with a 'C-Disposition: attachment' and it displayed anyhow. cvs repository 07/02/2004 valdis.kletnieks@vt.edu lib/exwin.tcl - first cut at separable ftoc and msg panes cvs repository 06/18/2004 welch@panasas.com Updating version to 2.7.0 in preparation for a release cvs repository 06/14/2004 welch@panasas.com mh.tcl: Slight tweak to version detection to make it more robust. bogo.tcl: moved misc/mybogo.tcl to lib/bogo.tcl - this is a wrapper around spamassasin or other spam filters lib/app-defaults-mono: removed "blue" from the monochrome Xdefaults app-defaults: added file magic strings for PDF documents force the frame padding to 0 because it is non-zero in 8.4 cvs repository 05/22/2004 cwg-exmh@deepeddy.com exmhwrapper - Prepend the hostname if we're running on the local host. This allows bifffolder to work even if it's on a different machine. cvs repository 05/11/2004 cwg-exmh@deepeddy.com mime.tcl - Don't display part inline by default if its disposition is "attachment". cvs repository 09/29/2003 cwg-exmh@deepeddy.com quote.tcl - In Quote_MultipartDefault, bulletproof against undefined numParts defaulting to zero. cvs repository 08/28/2003 cwg-exmh@deepeddy.com ftoc.tcl - In FtocCommit, clear all unseen messages at the same time. (modification of the 7/13 change) cvs repository 07/13/2003 welch@acm.org ftoc.tcl: patch from Louis Mamakos to batch up the sequence updates when doing large deletes. cvs repository 07/11/2003 welch@acm.org inc.tcl: patch from Glenn Burkhardt to add -user to inc command cvs repository 06/11/2003 haldevore@acm.org Modified misc/mybogo.tcl to save and restore target cvs repository 06/11/2003 haldevore@acm.org Added code, and a README for Patrick Carr's Bogofilter stuff to misc directory cvs repository 06/11/2003 haldevore@acm.org Added code, manpage, and a README for Justin Mason's mhthread to misc directory cvs repository 06/11/2003 haldevore@acm.org patch from "Klaus Elsbernd" mh.tcl It clears the mhPriv(otherpriv) variable, which otherwise grows infinitly, when reading .exmhcontext-File multiple times and writing it afterwards. cvs repository 06/01/2003 welch@panasas.com mime.tcl - add skipping of blank lines to help find the start of PGP messages better. Based on fix by Joel Hatton cvs repository 05/19/2003 welch@panasas.com pgpPgp65.tcl - Added +compatible=off to batchmode flags (Neil Rickert) added version check improvement for PGP 6.5 (Neil Rickert) (added . - and _ to the pattern, too (kre)) preferences.tcl - In the toplevel display, changed row of unsorted buttons to a sorted listbox cvs repository 04/21/2003 valdis.kletnieks@vt.edu pgpMain.tcl - I can't type, fix elsif to elseif cvs repository 04/21/2003 valdis.kletnieks@vt.edu patch from Kevin Oberman lib/pgpMain.tcl - add tweak to support Mutt-generated pgp-sign messages cvs repository 04/08/2003 haldevore@acm.org patch from Chris Garrigues thread.tcl Fix to prevent threading from erasing unseen sequence cvs repository 04/04/2003 welch@panasas.com sequences.tcl - removed Exmh_Debug from Seq_Trace fcache.tcl - removed Exmh_Debug flag.tcl - restored variable trace on flist(totalCount,unseen) exmh.install - bumped date on the release cvs repository 04/03/2003 haldevore@acm.org patch from Klaus Elsbernd elsbernd@dfki.uni-kl.de mh.tcl fix variable usage in sequences, corrects a problem with private sequences cvs repository 04/03/2003 haldevore@acm.org select.tcl patch from Robert Elz (kre@munnari.OZ.AU) select.tcl - Thorough input validation when selecting message by keying message number cvs repostiory 4/2/2003 welch@panasas.com flist.tcl, sequences.tcl - Repaired the change made on 4/1 cvs repository 04/02/2003 valdis.kletnieks@vt.edu exmh.MASTER, lib/widgets.tcl - set a default cursor of 'left_ptr' (otherwise enlightenment 0.16.5 doesn't play nice with XFree86 4.3.0 cursors) cvs repository 04/02/2003 haldevore@acm.org flist.tcl - Only call Fcache_Redisplay if folders being cached cvs repostiory 4/1/2003 welch@panasas.com flist.tcl, sequences.tcl - Fix to call Fcache_Redisplay from the trace on flist. cvs repository 04/01/2003 haldevore@acm.org Multiple fixes from Robert Elz (kre@munnari.OZ.AU) select.tcl, html/guide.html - Select message by typing now allows "s" to show the message or "-" to go to the prior message mh.tcl - Ignore garbage in sequence files main.tcl - Add Disable/Enable button to debug log window extrasInit.tcl, sedit.tcl, seditMime.tcl - add preference item to make insertion of x-mailer header optional and check the item (applicable to Sedit only) cvs repository 03/31/2003 haldevore@acm.org select.tcl, removed fix for non-numeric typing cvs repostiory 3/30/2003 welch@panasas.com sequences.tcl, flist.tcl, main.tcl, exmh-bg.MASTER - restructure sequence searching so it is done in the background process like it used to be in exmh-2.5 select.tcl - fixed non-numeric typeing mh.tcl - added stubs for 2.5 APIs Mh_MarkSeen and Mh_MarkUnseen app-defaults - removed hardwired "unseen" exmh.install, etc, changed version to 2.6.3 cvs repository 03/26/2003 haldevore@acm.org flag.tcl - Applied patch sent to exmh-users by dglo@ssec.wisc.edu 2.6.2 Tarball created 3/21, uploaded 3/25 exmh-2-6-2 CVS tag cvs repository 03/21/2003 welch@panasas.com scan.tcl - Added -noheader to the scan invocation. ftoc.tcl - protected against unfound message in Ftoc_MoveFeedback, although I'm unsure how this error could have come up. cvs repository 03/20/2003 haldevore@acm.org html/reference.html - Expand description of Sequences... menu cvs repository 03/18/2003 haldevore@acm.org msgShow.tcl - change MsgShowListHeaders to keep all protocols and include the protocol in the menu item. This should be made smarter or prettier someday. addr.tcl - add escaped quotes around search expression so it survives as a single argument after the eval. cvs repository 03/18/2003 valdis.kletnieks@vt.edu msgShow.tcl - Fix MsgShowListHeaders to be pedantically correct - it had been accidentally picking the first field only. It now loops through each field and only saves http, https, and mailto URIs. cvs repository 03/18/2003 welch@panasas.coM exmh.install - bumped up date for 2.6.2 msgShow.tcl - added \n adn \t to the white-space removal in the Hook_MsgShowListHeaders proc. cvs repository 03/15/2003 valdis.kletnieks@vt.edu seqwin.tcl - bug fix for brent's previous bug fix. Make sure that $seqwin(startuphidden) is set before we call SeqWinToggle cvs repository 03/14/2003 welch@panasas.com sequences.tcl, seqwin.tcl - Bug fixes for previous submit bindings.tcl - fixed this to properly allow users to override bindings. This is an ancient bug! cvs repository 03/12/2003 welch@panasas.com sequences.tcl, seqwin.tcl - Delay the initial display of the sequences window. cvs repository 03/12/2003 valdis.kletnieks@vt.edu fcache.tcl - Fix problem with fcache listing. The rows would be packed to fit 'folder' and then expanded with 'folder:NNN' for unseen msgs, which could cause it to wrap to a next line, leaving you with (for example) two rows and an orphan on a 3rd row. cvs repository 03/11/2003 welch@panasas.com flag.tcl - Removed trace on flist(totalcount,$mhProfile(unseen-sequence)) and replaced with explicit call to Flag_Trace in Flist_Done. This is to reduce the amount of variable trace firing and speed things up a bit. flist.tcl - Removed some ancient debugging code that was an ancient ancestor of the unseen/sequences window. folder.tcl - Shifted the Ftoc_ShowSequences call to eliminate one extra redisplay. ftoc.tcl - added various debugging and fixes to Ftoc_FindMsg, but the trouble was really caused by a -header flag in a users .mh_profile for scan. mime.tcl - fixed the MimeHeaderSort procedure to use the patterns in Folder-Display and Folder-Surpress correctly, and to work better with non-defaults (Tom Lane's fix) seqwin.tcl - eliminated one update idletasks to eliminate screen updates. cvs repository 02/21/2003 welch@panasas.com ftoc.tcl - Reverted change to the binary search in Ftoc_FindMsg because the new method sometime causes stack traces because the nextlineno computation returns values out of range. mh.tcl - added call to Mh_SequenceUpdate to Mh_SetCur seq.tcl - removed Mh_SequenceUpdate call from Seq_Set, because that procedure is usually called with the results of Mh_Sequence, so we were reading sequence information and then immediately writing it back out. Also removed "unseen" from the seqAlwaysShow preference item. Otherwise you couldn't clear that setting because of the way preference defaults works. seqwin.tcl - fixed stack trace by adding initialization for seqwin(folders,$seq) cvs repository 02/20/2003 welch@panasas.com folder.tcl - fixed Folder_IsShared parameter definition that conflicted with global variable. cvs repository 02/19/2003 welch@panasas.com flist.tcl - fixed the Flist button, which was broken by the flistcache Also fixed the autoSort feature in Flist_UpdateUnseen cvs repository 02/18/2003 welch@panasas.com flist.tcl, folder.tcl - oops! botched change related to Flist_UpdateUnseen described below. Repackaged 2.6.1 and updated cvs tag. cvs repository 02/18/2003 welch@panasas.com Makefile, exmh.README, exmh.install, version.sed, exmh.README.html, index.html, software.html 2.6.1 release cvs tag exmh-2-6-1 cvs repository 02/18/2003 welch@panasas.com mime.tcl - MimeHeaderSort fix from Tom Lane so that it displays headers that appear in Header-Display first, before unsuppressed ones. folder.tcl - Eliminated call to Flist_UpdateUnseen from FolderChange, which does a little too much. This means that exmh now keeps track of the "unvisited folders" better for Ftoc_NextFolder ('F' binding) html.tcl - added Http_stop call to Html_Stop app-defaults-color - changed unseen sequence back to having a blue foreground. mime.types - added "pps" for application/powerpoint cvs repository 02/17/2003 welch@panasas.com extrasInit.tcl, pgp.tcl - picked up pgp(extpass) patch from Alexander Zangerl flist.tcl - FlistFindSeqsInner added check to eliminate calls to Seq_Set if the sequence information for a folder hasn't changed ftoc.tcl - Changed msgtolinecache and linetomsgcache so that they have no entries for empty ({}) mappings. I was running into a mapping for the last text widget line that didn't contain a message and ended up messing up incremental folder scans Ftoc_MsgNumber doesn't cache anything if there is no mapping Retrieved FtocShowUnseen from exmh-2.5 and use that for the unseen sequence instead of the more general search main.tcl - a slight varition on the fix that slipcon made to the millisecond time stamps. mh.tcl - rooted out an "array unset" that doesn't work in Tcl 8.0 thread.tcl - fixed call to Flist_ForgetSequence (changed to Seq_Forget) Minor HTML cleanup, including pointer to the Wiki. I added comments to several files that identify old exmh APIs, including flist.tcl, folder.tcl, mh.tcl, msg.tcl, cvs repository 02/16/2003 cwg-exmh@deepeddy.com msg.tcl - Only call Ftoc_ShowSequence in MsgChange if we have a valid message. ftoc.tcl - Bulletproof Ftoc_ShowSequence cvs repository 02/10/2003 valdis.kletnieks@vt.edu exmh-strip.MASTER, lib/aliases.tcl, lib/background.tcl, lib/busy.tcl lib/buttons.tcl, lib/editor.tcl, lib/exwin.tcl, lib/faces.tcl lib/flist.tcl, lib/folder.tcl, lib/getnews.tcl, lib/glimpse.tcl lib/inc.tcl, lib/mh.tcl lib/mime.tcl lib/seqwin.tcl Add greppable text to Exmh_Debug call cvs repository 02/10/2003 valdis.kletnieks@vt.edu lib/fcache.tcl - Put in John Beck's fix for extraneous 'folder:0' in the fdisp cvs repository 02/10/2003 cwg-exmh@deepeddy.com scan.tcl - fix lineVar and line references to linenoVar and lineno. cvs repository 02/09/2003 welch@panasas.com Making the 2.6 release, cvs tag exmh-2-6 These files were updated: COPYRIGHT Makefile exmh.CHANGES exmh.README exmh.install version.sed lib/html/exmh.README.html lib/html/index.html lib/html/software.html In addition, this tar file of handy scrips was uncommited in my misc dir. misc/mhutils.tar.gz cvs repository 02/09/2003 welch@panasas.com main.tcl - added microsecond granularity time stamps to log messages msg.tcl - added Msg_ShowCurrent compatibility routine cvs repository 02/07/2003 cwg-exmh@deepeddy.com folder.tcl, ftoc,tcl, scan.tcl - Call Ftoc_ShowSequences in Ftoc_Update on the new messages. Cal Ftoc_ShowSequences in FolderChange. Don't call Ftoc_ShowSequences in ScanFolder and Scan_Inc. This both cuts down on the number of lines we call Ftoc_ShowSequences on and eliminates a timing window that was generating "Cannot find $msgid ($minmsgid,$maxmsgid)" warnings. cvs repository 11/07/2002 valdis.kletnieks@vt.edu mh.tcl, flist.tcl, tclIndex - add new function MhGetSeqCache to speed up flist/sequence handling. We now only call MhReadSeqs once per folder, and skip over sequences listing in $seqwin(nevershow). Also, migrate some code into new function FlistFindSeqsInner so that it can be called with BgRPC to make exmh-bg happier. cvs repository 11/1/2002 cwg-exmh@deepeddy.com seqwin.tcl - prepend sequence names with "pane" when using to name panes because a pane can't start with a Capital letter. cvs repository 10/30/2002 cwg-exmh@deepeddy.com mh.tcl - When compacting sequences, don't compact if it's already compacted. cvs repository 10/29/2002 cwg-exmh@deepeddy.com msg.tcl - In Msg_Show, if there are no messages in the sequence we're trying to show, then show 'cur'. sequences.tcl - Minor cleanups in Seq_Trace and improvements to debug code. flist.tcl - in FlistResetVars, sort array names so that totalcount gets cleared after seqcount in order to keep it from going negative. mh.tcl - When rewriting the sequences file, don't expand the other sequences. cvs repository 10/28/2002 cwg-exmh@deepeddy.com msg.tcl, editor.tcl, folder.tcl, ftoc.tcl, main.tcl, mh.tcl, sequences.tcl, thread.tcl - Remove message checkpoint code which was originally intended to work around an mh mark bug, but which now seems unneeded and needlessly complex (causing messages to not get unmarked in various contexts). cvs repository 10/16/2002 haldevore@acm.org pick.tcl - Adaptation of Ted Cabeen's "catch up to current" code cvs repository 09/23/2002 cwg-exmh@deepeddy.com mh.tcl - some bulletproofing in MhReadSeqs. cvs repository 09/21/2002 cwg-exmh@deepeddy.com ftoc.tcl, msg.tcl, pick.tcl, scan.tcl, thread.tcl - Remove the $folder argument from Ftoc_ShowSequences and Ftoc_Update because it's always the current folder; break Ftoc_ShowSequence out of Ftoc_ShowSequences; add an optional argument to both procedures that specifies the particular message ids to show; and change most calls to Ftoc_ShowSequences to call Ftoc_ShowSequence or to specify the optional argument or both. cvs repository 09/09/2002 Robert Elz via welch@panasas.com ftoc.tcl - Fixed reference to $L cvs repository 08/26/2002 Robert Elz via cwg-exmh@deepeddy.com pick.tcl - change the order of the arguments to pick to get around nmh bug. cvs repository 08/23/2002 cwg-exmh@deepeddy.com Intro.html, Search.html, custom.html, exmh.README.html, guide.html, overview.html, reference.html, tutorial.html - Documentation updates for all my recent patches. cvs repository 08/22/2002 cwg-exmh@deepeddy.com mh.tcl - Cache sequences so we don't read the .sequences files over and over and over. seqwin.tcl, sequences.tcl - New preferences item for orientation of sequences panes. seqwin.tcl - Fix "Hide When Empty" and possibly "Icon Window". sequences.tcl - Speed up Seq_Del. pick.tcl - Redisplay sequences at the end of PickMarkSeen. msg.tcl - Don't use Ftoc_MsgIterate in Msg_Mark and Msg_UnMark. cvs repository 08/21/2002 cwg-exmh@deepeddy.com flag.tcl - Don't die in Flag_MsgSeen if flist(totalcount,unseen) is undefined. app-defaults - Msg_MarkUnseen is now {Msg_Mark unseen}. msg.tcl - left a $ off of $mhProfile(unseen-sequence) ftoc.tcl - Needed quotes around argument to Exmh_Status. cvs repository 08/20/2002 cwg-exmh@deepeddy.com app-defaults-color - Change default colors of ftoc so highlighted sequences will appear better. seqwin.tcl - New File; Replacement for unseenwin...more generalized. sequences.tcl - seqwin hooks are in here. flist.tcl - Initialize flist() elements differently; Flist_FindUnseen is now Flist_FindSeqs and calls Seq_Set instead of doing it by hand. ftoc.tcl - Ftoc_FindMsgs replaces Ftoc_FindMsg and handles lists of messages; Ftoc_MsgNumbers replaces Ftoc_MsgNumber and handles lists of lines; ftoc_NewFtoc now takes an optional argument to specify the lines; defaulting again to ftoc(lineset); remove Ftoc_MarkSeen as dead code; New function Ftoc_CurLines and rewrite Ftoc_Iterate to use Ftoc_CurLines; new function Ftoc_MsgIterate to use instead of Ftoc_Iterate in several places; call Msg_Show instead of Msg_ShowCurrent and Msg_ShowUnseen; call Seq_Del and Seq_Add instead of Mh_SequenceUpdate or Seq_RemoveMsg mh.tcl - Call Seq_Add and Seq_Del instead of Mh_SequenceUpdate; Seq_Expand moved back here and named back to MhSeqExpand; Seq_Modify rewritten, moved back here and named back to MhSeq. msg.tcl - Merge Msg_ShowCurrent and Msg_ShowUnseen into Msg_Show; Call Ftoc_MsgNumbers instead of Ftoc_MsgNumber; Call Ftoc_FindMsgs instead of Ftoc_FindMsg; Call Seq_Add or Seq_Del instead of Seq_RemoveMsg or Mh_SequenceUpdate; Call Ftoc_MsgNumbers or Ftoc_MsgIterate where it's simpler than Ftoc_Iterate; app-defaults, background.tcl, inc.tcl, pgpWWW.tcl, user.tcl - Use Flist_FindSeqs instead of Flist_FindUnseen. bindings.tcl, folder.tcl, inc.tcl - Msg_ShowCurrent and Msg_ShowUnseen are now Msg_Show. editor.tcl - use new Ftoc_FindMsgs instead of Ftoc_FindMsg pick.tcl - use Seq_Del instead of Seq_RemoveMsg. print.tcl - Use Ftoc_MsgIterate instead of Ftoc_Iterate. scan.tcl - Use Ftoc_MsgNumbers instead of Ftoc_MsgNumber; call Ftoc_ClearMsgCache and Ftoc_ShowSequences in Scan_ProjectSelection. thread.tcl - Use Ftoc_MsgNumbers instead of Ftoc_MsgNumber; Ftoc_FindMsgs instead of Ftoc_FindMsg bindings.tcl, fcache.tcl, flag.tcl, flist.tcl - use $mhProfile(unseen-sequence) instead of hard coding 'unseen'. extrasInit - remove UnseenWin initialization; change topten reference to unseenWin to be to seqWin instead. cvs repository 08/08/2002 cwg-exmh@deepeddy.com sequences.tcl, flag.tcl - move flag handling from Seq_Trace into new Flag_Trace. sequences.tcl - code cleanup. flist.tcl - Don't unset totalcount, it breaks Flag_Trace; set to zero instead. cvs repository 08/06/2002 cwg-exmh@deepeddy.com folder.tcl - Mark display valid when we change folders. unseenwin.tcl - Change folder if the display isn't valid. cvs repository 08/06/2002 cwg-exmh@deepeddy.com app-defaults, fcache.tcl, flag.tcl, flist.tcl, ftoc.tcl, inc.tcl, main.tcl, mh.tcl, msg.tcl, pick.tcl, scan.tcl, sequences.tcl thread.tcl, unseenwin.tcl - 1) Renamed flist(new,???) to flist(seqcount,???,unseen), flist(newseq,???) to flist(seq,???,unseen), and flist(newMsgs) to flist(totalcount,unseen) and generalized many of the functions which referred to them to have a sequence argument. 2) Reorganized sequences code into its own file from mh.tcl and flist.tcl; involved renaming of functions which is why so many files are touched in this patch. 3) As a result of the above two items merged Mh_Sequence and Flist_UnseenMsgs, which once generalized did almost exactly the same thing into the single funciton Seq_Msgs. 4) Did most of the prep-work for generalization of the unseen window to be a general sequences window so that now all the needed data is tracked. The next step will be to use that data. cvs repository 08/03/2002 cwg-exmh@deepeddy.com unseenwin.tcl - Reindent all code to be more standard. I was having a problem with emacs reindenting this as I worked on it and making it hard to tell my real changes from the indents, so I'm formatting the baseline more "correctly" so that "cvs diff" can be useful. cvs repository 07/25/2002 welch@panasas.com lib/app-defaults-color: added "urgent" sequence so it shows up in the Sequences menu. It has -foreground purple by default. lib/exwin.tcl: added "raise" to Exwin_Toplevel so that hidden windows have a better chance of coming to the top when they are opened. lib/inc.tcl: sort the MyIncTmp directory before processing so that messages get ordered date correctly after filtering. lib/mh.tcl: fixes to turn of regexp special characters from folder names - contributed by John Farrell lib/mime.tcl: lib/uri.tcl: Added way to display defered HTML inside exmh. Contributed by Tomas Gradin lib/msg.tcl: Added Msg_Mark and Msg_UnMark, but these are not used. Thought I needed them for Sequence support, but the Sequences... menu already works without them. lib/seditBind.tcl: Moved the SeditBeautify binding to the correct bindtag so it doesn't fire on the main message window. lib/widgets.tcl: Added catch inside Widget_ReEvalCmd cvs repository 07/26/2002 cwg-exmh@deepeddy.com folder.tcl - Call Msg_Change with skipdisplay in Folder_Pack too. cvs repository 07/26/2002 cwg-exmh@deepeddy.com scan.tcl,ftoc.tcl - Found the bug in ftoc.tcl which was causing the current message to get lost. cvs repository 07/25/2002 cwg-exmh@deepeddy.com flist.tcl - New proc Flist_SetUnseen which can be called instead of Flist_AddUnseen to avoid calling Flist_ForgetUnseen. Call it in Flist_UnseenMsgs. Also remove some ancient dead code from the end of Flist_AddUnseen. folder.tcl, flist.tcl - Move ftoc(autoSort) test from FolderChange to Flist_UnseenUpdate so that it will be called more in more cases. msg.tcl, folder.tcl - Add new possible value for second value to Msg_Change of "skipdisplay" which says to not change the message display when changing messages; then use this value in Folder_Sort so sorts don't cause the message display to rescroll to the top. This makes them much less anoying; pretty important if it gets called automatically by background processing. scan.tcl - In Scan_FolderForce, call Flist_UnseenMsgs instead of Flist_ForgetUnseen so that the folder doesn't move in the unseen window; also call Ftoc_Change because the current message can get lost somehow. cvs repository 07/22/2002 cwg-exmh@deepeddy.com scan.tcl - In ScanFolder, don't try to scan for only new messages if ftoc(numMsgs) is zero. cvs repository 07/22/2002 cwg-exmh@deepeddy.com ftoc.tcl, msg,tcl, scan.tcl - Eliminate optional "line" argument to Ftoc_FindMsg, not incidently removing *all* the code that between the old location and the new location in my patch of 7/19; as a result, also remove the optional line argument to Ftoc_Change and the msgid argument to Msg_Change; also, of course, change all the callers of these functions, and remove the dead Msg_ShowWhat proc. This gives us a net reduction in code and makes it all somewhat clearer. Let's see what I broke by doing this. pgpMain.tcl, pgpOld.Tcl - Call Msg_Change, not MsgChange. cvs repository 07/19/2002 cwg-exmh@deepeddy.com ftoc.tcl - In Ftoc_FindMsg, move the cache check until after the processing of $line. cvs repository 07/18/2002 cwg-exmh@deepeddy.com scan.tcl - Don't clear the "+" from cur. cvs repository 07/15/2002 valdis.kletnieks@vt.edu pgpExec.tcl - multiple fixes. Added a second call to CheckSuccess to both Exec_Encrypt and Exec_EncryptSign (and a 'file delete' to clean up beforehand) so we actually *fail* if the second try doesn't work. Also, fixed the regexp in CheckSuccess - it failed to deal with multiple lines of output, and I added gnupg 1.0.7 support. cvs repository 07/15/2002 cwg-exmh@deepeddy.com flist.tcl - in Flist_UnseenUpdate, don't push the folder onto the unvisited list if it's the current folder. cvs repository 07/15/2002 cwg-exmh@deepeddy.com folder.tcl - Gratitiously change the name of the 'f' variable wherever it's used either to 'folder' or to 'file' to be more consistent with other code. cvs repository 07/13/2002 cwg-exmh@deepeddy.com flist.tcl,folder.tcl - Completely back out the fixpacksort patch from two years ago that hal installed because of the unseenwindow shuffling that occurs and besides the Flist_ForgetUnseen proc is supposed to handle this case. If there is indeed a problem that occurs, we can fix it in a way that won't shuffle the unseen window. cvs repository 07/12/2002 cwg-exmh@deepeddy.com flist.tcl - Remove call to Flist_ResetUnseen in Flist_UnseenUpdate so that the unseen window won't get shuffled all the time. cvs repository 07/12/2002 cwg-exmh@deepeddy.com scan.tcl - Back out the removal of Ftoc_Reset from 7/3/2002 as well as yesterday's attempt to fix some of the problems caused by that bad idea. cvs repository 07/11/2002 cwg-exmh@deepeddy.com scan.tcl - in ScanFolder, we don't know what the last message is yet, so we need to use Widget_Text_End instead. Also, call Ftoc_RescanLine if need be. cvs repository 07/10/2002 cwg-exmh@deepeddy.com ftoc.tcl - In Ftoc_ClearCurrent, if ftoc(curLine) isn't set use Mh_Cur to find where we're clearing. cvs repository 07/03/2002 cwg-exmh@deepeddy.com folder.tcl, ftoc.tcl - Don't call Scan_Folder in FolderChange; properly initialize ftoc(displayValid) to 1 so that Scan_Folder will be called when needed. cvs repository 07/03/2002 cwg-exmh@deepeddy.com scan.tcl - Remove unnecessary call to Ftoc_Reset in ScanFolder cvs repository 07/02/2002 cwg-exmh@deepeddy.com folder.tcl - Call Flist_UnseenUpdate just before calling Scan_Folder in FolderChange cvs repository 07/02/2002 cwg-exmh@deepeddy.com scan.tcl - Remove bogus call to Flist_ForgetUnseen cvs repository 06/07/2002 welch@panasas.com lib/mime.tcl - Move the modification of application/octet-stream MIME types up a bit to be before the decision is made to display the type (patch from Diego Zamboni) cvs repository 06/06/2002 welch@panasas.com lib/ftoc.tcl - Fix to Ftoc_ClearMsgCache for unset vs. array unset buglet. cvs repository 05/01/2002 Hal DeVore lib/sedit.tcl - moved calls to SeditSend hooks to much earlier cvs repository 04/30/2002 welch@panasas.com A whole collection of patches. If marked with ** then I've lost track of who gave them to me and I apologize for that: exmh-strip.MASTER: added pref initialization to quiet errors caused by changes elsewhere in the main body of exmh install.tcl: fixed errors that occur when you try to display a dialog box (e.g., the Verify window) that is already displayed lib/addr.tcl: a new set of options for configuring LDAP (Mark Bergman) lib/extrasInit.tcl: help text updates about the uquoteAdd resource (**) lib/faces.tcl: fix for space-in-pathname problem (**) lib/fcache.tcl: New Feature! display the count of unseen messages in the folder cache. (Paul Menage) lib/html_get_http.tcl: trap errors from bad http: links lib/inc.tcl: tweaked feedback about inc'ed messages to do case-insensitive grep for Subject: (**) lib/mime.tcl: for for space-in-pathname problem lib/pgpExec.tcl: eliminated Exmh_Debug message that could dump out a massive keyring to the log, taking many many seconds (**) lib/unseenwin.tcl: fix to tolerate space-in-folder-name (I think) (**) cvs repository 04/04/2002-04/17/2002 cwg-exmh@deepeddy.com various files - some more code cleanup and a whole bunch of sequence related code tuning. cvs repository 04/03/2002 cwg-exmh@deepeddy.com lib/app-defaults, lib/app-defaults-color, lib/buttons.tcl, lib/exwin.tcl, lib/ftoc.tcl, lib/msg.tcl, lib/pick.tcl - Added 'Sequences...' menu; some code cleanup and a few bug fixes from the last change. cvs repository 03/28/2002 cwg-exmh@deepeddy.com lib/app-defaults-color, lib/app-defaults-mono, lib/exwin.tcl, lib/fdispColor.tcl, lib/ftoc.tcl, lib/ftocColor.tcl, lib/help.tcl, lib/mh.tcl, lib/msg.tcl, lib/pgpMain.tcl, lib/scan.tcl, lib/thread.tcl - Generalized unseen handling to display other sequences besides unseen. cvs repository 01/25/2002 slipcon@mercea.net lib/html/ppp.howto.html - fixed postfix instructions, via Kevin Oberman again. cvs repository 01/26/2002 valdis.kletnieks@vt.edu lib/ftp_get.tcl - add a 'catch' in case an FTP dies early, so we don't throw an error unsetting data(fd) if it was never set.. cvs repository 01/26/2002 valdis.kletnieks@vt.edu lib/app-defaults-color, lib/main.tcl, lib/html/custom.html - drop the need for c_st_background color setting, use same scheme as lib/sedit.tcl to propogate the value. The 'background msgs' color stays c_st_bg_msgs cvs repository 01/25/2002 slipcon@mercea.net lib/html/ppp.howto.html - added postfix instructions, using Kevin Oberman (oberman@es.net)'s diff cvs repository 01/24/2002 valdis.kletnieks@vt.edu lib/sedit.tcl - missed a readonly/disabled issue for Tk8.4 (status field) cvs repository 01/24/2002 valdis.kletnieks@vt.edu exmh-bg.MASTER, lib/main.tcl, lib/app-defaults-color, lib/html/custom.html So there *was* code using c_st_background. That color specification is now c_st_bg_msgs, and exmh-bg no longer tries to lookup a colorspec but just passes 'background' to Exmh_Status. cvs repository 01/23/2002 valdis.kletnieks@vt.edu lib/app-defaults-color, lib/html/custom.html - Default for c_st_error is now red, and the default for c_st_warn is purple (be more consistent with usual meaning of a red message indicating an error) cvs repository 01/23/2002 valdis.kletnieks@vt.edu install.tcl, lib/main.tcl - Do version test as per Jeff Hobb's suggestion. cvs repository 01/22/2002 valdis.kletnieks@vt.edu lib/aliases.tcl, lib/background.tcl, lib/env.tcl, lib/error.tcl, lib/faces.tcl, lib/flist.tcl, lib/folder.tcl, lib/folderNew.tcl, lib/inc.tcl, lib/main.tcl, lib/mime.tcl, lib/msg.tcl, lib/pick.tcl, lib/print.tcl, lib/scan.tcl, lib/seditSel.tcl, lib/source.tcl, lib/thread.tcl, lib/urlFace.tcl Clean up red/purple/blue hardcoded values for Exmh_Status lib/app-defaults-color, lib/main.tcl - clean up dead unused code for c_st_background (which is used as a *foreground* color gaak) c_st_background is now the *background* color for the status field cvs repository 01/22/2002 valdis.kletnieks@vt.edu install.tcl - tkEntryBackspace handling for Tk8.4a2 and later namespaces cvs repository 01/22/2002 valdis.kletnieks@vt.edu lib/main.tcl - add new procedure Tcl_Tk_Vers_Init to do per-release tweaking of the environment. Currently used to re-expose commands moved to private namespace in Tk8.4a2. cvs repository 01/20/2002 valdis.kletnieks@vt.edu lib/ispell.tcl - fix old syntax error finally caught by tcl8.4a4. cvs repository 12/07/2001 kchrist lib/pgpExec.tcl - Fixed "GPG silently ignores untrusted keys during encryption" bug. Thanks to Ben Escoto. cvs repository 12/06/2001 kchrist lib/mime.tcl: Do not call viewer if mailcap rule has needsterminal attribute. When using Mime_Magic to replace application/octet-stream make sure to replace entire content-type and not just the "octet-stream" subtype. lib/seditExtras.tcl: Fixed a bug in SeditInsertFile that caused text to be lost when quoting. Previous code assumed headers were always present and had to be removed. lib/pgpMain.tcl: Fixed the "Always choose the sign key." option. Fixed a clearsigning bug. Modified interpretation of app/pgp header to avoid hang. lib/pgpExec.tcl : Exmh can now parse the GnuPG options file and lib/pgpGpg.tcl : identify the "default-key" (same as "myname" in PGP). Added "--status-fd 2" to args_decrypt so that the output can be parsed with Pgp_InterpretOutput. cvs repository 11/21/2001 Brent Welch lib/main.tcl: Moved WM_SAVE_YOURSELF registration a bit later because it has an Exmh_Checkpoint side-effect that causes exmh to forget the current folder. exmh.strip.MASTER fixed #! line so it gets installed right. lib/mh.tcl: Plugged file descriptor leak in Mh_ParseProfile Fixed ParseProfile to handled indented continuation lines lib/seditExtras.tcl: Tweaked paragraph formatting in Sedit to honor requested line length and the anticipated repl prefix length. custom.html: fixed m_tagnames documentation software.html: fixed uudeview URL cvs repository 11/15/2001 Valdis Kletnieks lib/folders.tcl: Fix typo in function name cvs repository 08/23/2001 kchrist lib/pgpWWW.tcl: Comment in switch statement causing problems. cvs repository 07/13/2001 Brent Welch lib/exmh.install.tcl: Changed release date to 7/13 lib/html/index.html: Changed release date to 7/13 tagged and released exmh 2.5. CVS tag exmh-2-5 cvs repository 07/13/2001 Brent Welch lib/mime.tcl: Fixed Mime_WithTextHiding to catch errors and returns from its uplevel call, fixing a file descriptor leak from Mime_ShowMsWord cvs repository 07/11/2001 Brent Welch ftp.expect.MASTER: inc.expect.MASTER: Changed to a #!/bin/sh header with exec hack to be able to insert the -- flag to expect install.tcl: Changed the expect patching to match the above change lib/pgpMain.tcl: lib/mime.tcl: Changed MsgTextHighlight to Msg_TextHighlight lib/msgShow.tcl: Added Msg_HighlightInit lib/sedit.tcl: Added SeditBeautify from John Beck lib/seditBind.tcl: Added "highlight" virtual function to sedit bindings lib/app-defaults: Added binding to sedit to beautify it. cvs repository 07/10/2001 Brent Welch lib/editor.tcl: A -- is passed to the exmh-async script to turn off any argument/flag parsing by wish. This means you can safely pass "-c" or "-geometry" arguments to the programs spawned by the exmh-async wrapper script. exmh-async.MASTER: Removed a split/join construct that screwed up attempts to pass arguments like {cal SetSyn("mail")} to editors. lib/mime.tcl: Fix to highlighting text range from John Beck. lib/msgShow.tcl: Tweaks to highlighting from John Beck. cvs repository 07/09/2001 Brent Welch Makefile: exmh.README: exmh.CHANGES: lib/html/exmh.README.html: lib/html/index.html: lib/html/software.html: version.sed: exmh.install: Changing version number to 2.5 exmh-bg.MASTER: exmh.MASTER: Fixed initialization of exmh(userLibrary) inc.expect.MASTER: Fixed !# line so it gets installed right lib/app-defaults-color: Added resources for message highlighting based on the jcl-beautify code. lib/autorefile.tcl: Contributed code by John Carroll lib/fdispColor.tcl: lib/fdisp.tcl: Added use of c_unseenBg and c_movedFg color resources for further refinement of unseen and moved messages. lib/inc.tcl: Cleanup of Inc_Expect lib/mailcap.tcl: Fixed bug in mailcap parsing code that didn't quote & in rules, leading to message corruption in SaveAttachments code. lib/mh.tcl: minor tweak to variable unset lib/mime.tcl: Added highlightText option and calls to MsgTextHighlight. * lib/msgShow.tcl: Added MsgTextHighlight and the jcl-beautify code, with minor changes to separate the bug reporting header highlighting into a different hook. There is now a "message show" hook that operates on the whole message, a "message highlight" hook that only operates on the text regions of a message. lib/pgpMain.tcl: Added call to MsgTextHighlight. lib/pop.tcl: Fixed Pop_Dialog so it works right with multiple hosts. cvs repository 05/31/2001 kchrist lib/scan.tcl: Allow arguments in scan-proc configuration. lib/app-defaults: Have "Use message as draft" call Msg_CompUse. This sidesteps an internal bug in MsgComp. To fix the bug MsgComp needs to be drafts-folder aware like Mh_CompSetup. cvs repository 05/18/2001 bmah lib/extrasInit.tcl: lib/pgpBase.tcl: PGP detection code now tries to execute a program (e.g. "gpg --version") and parse the output to determine presence of installed versions. Former versions only checked the existence of files. cvs repository 05/16/2001 kchrist lib/sedit.tcl: Make sure exmh($id,action) survives a 'Keep on send'. cvs repository 05/15/2001 Brent Welch Makefile: exmh.README: exmh.CHANGES: lib/html/exmh.README.html: lib/html/index.html: lib/html/software.html: exmh.install: Changing version number to 2.4 version.csh: version.sed: Scripts to help with version changes. (I don't think I ever committed things at this point - hence 2.5) cvs repository 05/14/2001 kchrist Fixed a bug in which a corrupt context would prevent exmh from starting. Problem was caused by direct calls to 'repl' instead of wrapping them inside a (context-aware) MhExec call. lib/main.tcl: Moved nmh-vs-mh identification to Mh_Init procedure lib/mh.tcl and replaced 'exec repl...' calls with 'MhExec repl...' calls. Note that MhParseProfile is called first since MhExec may need $phProfile(path). cvs repository 05/11/2001 kchrist A bunch of changes having to do with making sure exmh($id,action) is there when we need it. Also... Replaced Sedit_Mailto with Msg_Mailto (extending Ovidiu's patch). Replaced exmh(ctype) with exmh($id,action). lib/editor.tcl: Set exmh($id,action) in Sedit_DraftID. lib/error.tcl: Call Edit_DraftID instead of EditWhatNow directly so that exmh($id,action) gets set. lib/html_links.tcl: Call Msg_Mailto instead of Sedit_Mailto. lib/mh.tcl: Made sure exmh($id,action) is set when comp'osing and reset when done. lib/msg.tcl: Turned Msg_CompTo into Msg_Mailto as replacement for Sedit_Mailto. Made new Msg_CompTo. Removed exmh(ctype). Set exmh($id,action) in MsgComp and Msg_Edit. Moved DecodeURL from seditExtras into here and renamed it to MsgDecodeURL. lib/sedit.tcl: Don't check if exmh($id,action) or pgp(version,$id) exist before using them. If they don't it is a bug we should catch and fix. Modified call to SeditSetIsigHeaders. lib/seditExtras.tcl: Modified parameters to SeditSetIsigHeader. Replaced Sedit_Mailto with a stub that calls Msg_Mailto. Removed DecodeURL. lib/tclIndex: New one needed because functions were moved. lib/uri.tcl: Call Msg_Mailto instead of Sedit_Mailto in URI_StartViewer. cvs repository 05/10/2001 Brent Welch exmh.MASTER: exmh-bg.MASTER: Removed auto_reset from auto_path_update and add exmh(userLibrary) to auto_path very early. inc.expect.MASTER: Code cleanup and fix to ensure that the password is not echoed in the scan listing. lib/addr.tcl: Adopted patch for LDAP searching lib/background.tcl: Removed extra call to User_Layout from Background_Init lib/env.tcl: We only chmod exmh(tmpdir) if it does not already exist to avoid setting permissions on /tmp, /usr/tmp, etc. lib/extrasInit.tcl: Added utf-8 to possible set of text charsets This is used when setting the initial type in sedit. lib/main.tcl: Removed the exmh(userLibrary) preference setting. This is hardwired (the code is in exmh.MASTER) to be either ~/.exmh/lib (a new, preferred value) or ~/.tk/exmh (the old, historical location) The first directory that exists is used. lib/pop.tcl: Minor tweak to focus settings in password dialog. lib/seditBind.tcl: Added auto_loads to try and avoid loosing bindings when Tk library files are loaded. cvs repository 04/20/2001 Ovidiu Predescu lib/uri.tcl (URI_StartViewer): Invoke Msg_CompTo instead of Sedit_Mailto to correctly support external editors. lib/sedit.tcl (Sedit_Start): Better check for PGP variables so we don't get a runtime error if PGP is not fully enabled in a particular installation. lib/msg.tcl (Msg_CompTo): Accept a generic mailto: URI as argument, instead of a simple email address. Modify the draft according to this mailto: URI so that it has the right content before being passed to the editor, which may be an external editor. cvs repository 04/10/2001 Brent Welch exmh-strip.MASTER: extracted code from mime.tcl into a utility script that strips attachments from mail and replaces them with message/external-body parts that reference the extracted file. lib/app-defaults: Added mappings from utf-8 charset to iso10646 fonts lib/env.tcl: switched from TMPDIR environment variable to exmh(tmpdir) so that we don't pollute the environment with our choice of temp directory. This confuses some programs, especially gnuclient. lib/mime.tcl: Fixed message/external-body for the local-file access case. lib/inc.tcl: Added guard against undefined exmh(slocal) to Inc_Init. Cleaned up check against stray files (e.g., "++") in the MyIncTmp directory. lib/folder.tcl: Added Folder_Cache calls when setting the move/copy folder so that the folder appears in the folder cache. cvs repository 03/03/2001 Brent Welch lib/inc.tcl: Eliminated the use of the expect wrapper around inc for the "presort-multidrop" and "multidrop" cases. This interferes with folks that have set up their .netrc file to have passwords. lib/fdispPopup.tcl: Eliminated noisey Exmh_Debug command lib/html/exmh-faq.html: Added #24 about scan .mh_profile entries that can cause problems. cvs repository 01/19/2001 Brent Welch lib/main.tcl: fixed test for MH version. Released exmh-2.3.1 1/19/2001 Brent Welch cvs repository 01/19/2001 Brent Welch lib/env.tcl: fixed installation error that was due to the addition of Env_Init to the installer. Only showed up when you installed without the .exmhinstall cache. Released exmh-2.3 1/17/2001 Brent Welch cvs repository 01/17/2001 Brent Welch lib/flist.tcl: Added catch for file system errors that could cause Flist to stop working - both when hitting the button and from the background process. cvs repository 01/15/2001 Brent Welch These files embed version information: Makefile exmh.README exmh.install lib/html/index.html lib/html/software.html lib/html/exmh.README.html lib/extrasInit.tcl: Moved POP3 mail host into the top-ten preferences. lib/html/exmh-faq.html: Added FAQ about using a POP3 mail server. lib/bitmaps: added a contributed set of bitmaps to replace text buttons. You'll need to set up your exmh-defaults to get these. See the lib/bitmaps/exmh-defaults file for an example. install.tcl: added call to Env_Init lib/env.tcl: Fixed it so that it doesn't chmod /tmp if that's what TMPDIR is set to. cvs repository 01/12/2001 Brent Welch lib/env.tcl - fix for symlink attack. Exmh now chooses /tmp/ as the default tmp directory. You can also set TMPDIR or EXMHTMPDIR, which was true in previous versions of exmh already. lib/pop.tcl - improved the password prompting dialog. inc.expect - fixed this to deal with the case where inc does *not* prompt you for a password. cvs repository 01/03/2001 Bruce A. Mah lib/pgpPgp5.tcl - Add +force to correct a problem with verifying the signatures of PGP5 clearsigned messages. From Dave Tweten , via the FreeBSD Project. cvs repository 01/03/2001 Hal DeVore exmh.TODO removed item 24 - support for nmh 1.0, already done removed item 33 - change name of /tmp/scancmds, it's already dependent on [Env_Tmp] cvs repository 01/03/2001 Hal DeVore lib/error.tcl - Remove file [Env_Tmp]/exmhErrorMsg if it exists prior to writing to it. Addresses a bug reported to BUGTRAQ. cvs repository 12/13/2000 Brent Welch lib/html/sedit.html - Added explanation from John Klassa about the Filter mechanism in Sedit. lib/folder.tcl - applied a fix for auto-packing folders from Chris Keane (I think it was Chris) The bug lead to incorrect scan listings when you used auto-pack. cvs respository 12/11/2000 Hal DeVore lib/sedit.tcl - removed duplicate SeditSetHeader proc cvs respository 11/22/2000 Hal DeVore lib/html/guide.html - Corrected a couple of improperly closed tags lib/sedit.tcl - patch from Chris Keane to eliminate the removal of charset in SeditSetHeader proc cvs repository 11/17/2000 Brent Welch lib/glimpse.tcl - Grouped some expressions with { } to avoid double-substitutions on file and directory names. If they had $ in them it would raise errors. cvs repository 11/08/2000 Brent Welch lib/inc.tcl - Added the option to use an expect script that wraps the "inc" program and deals with the password prompt. inc.expect.MASTER - the expect script cvs repository 10/25/2000 Anders Eriksson lib/mime.tcl - Headers are now displayed in the order expressed in mhProfile(header-display) cvs repository 10/23/2000 Brent Welch lib/ispell.tcl - replaced some debug "puts" with Exmh_Debug lib/uri.tcl - trim white space off the URI that is matched to handle the funky Visit links. lib/glimpse.tcl - fixed glimpse -V test during startup to handle both old and new versions of glimpse. cvs repository 09/21/2000 Valdis Kletnieks lib/glimpse.tcl - Glimpse 4.12.6 output /Mail//folder - the double slash gave a regexp indigestion. Fix to accept / or // after Mail cvs repository 09/21/2000 Valdis Kletnieks lib/pgpExec.tcl - fix 'set result' so 'PGP Get Key' and 'PGP Generate Key' work. cvs repository 09/21/2000 Valdis Kletnieks lib/pgpPgp65.tcl - fix a stupid regexp problem so it finds RSA keys cvs respository 09/15/2000 Hal DeVore lib/inc.tcl Added code to allow the use of procmail or any other mail-fetching-and-filtering tool directly from exmh. Original patch developed by Carl D. Roth, code updated and merged into current exmh by Chris Keane. cvs respository 09/13/2000 Hal DeVore lib/html.tcl Fixed preferences item spelling mismatch problem and solution pointed out by Ben Escoto cvs respository 09/07/2000 Hal DeVore lib/addr.tcl Fixed problem with some address book preferences getting clobbered. cvs respository 08/30/2000 Hal DeVore lib/seditMime.tcl applied patch from Chris Garrigues to prevent flowing of mhn directives when running sedit with formatting on send. cvs repository 08/28/2000 Valdis Kletnieks lib/html/software.html: Document 8.3.2 as most recent Tk/Tcl. cvs repository 06/28/2000 Hal DeVore lib/mh.tcl: added -noheader to "exec scan" in Mh_Forw_MungeSubj to prevent breakage when user .mh_profile specifies "scan: header", problem found by David Chin cvs repository 06/28/2000 Hal DeVore lib/folder.tcl: Got rid of a hardcoded path to ~/Mail cvs repository 06/27/2000 Bruce A. Mah lib/seditExtras.tcl: Add an "undo" feature for sedit shell, from John Klassa . cvs repository 06/27/2000 Hal DeVore lib/{mh.tcl,msg.tcl}: Add upward search for components, forwcomps, and replcomps. Add search for distcomps also. cvs repository 06/26/2000 Bruce A. Mah lib/{extrasInit,sedit,seditExtras}.tcl: Add the ability for sedit to filter the selected text region through an arbitrary UNIX command, from John Klassa . Released exmh-2.2 6/23/2000 Brent Welch cvs repository 06/22/2000 Valdis Kletnieks lib/receipt.tcl - generate proper Final-Recipient: field cvs repository 06/22/2000 Bruce A. Mah lib/html/exmh-faq.html: Added FAQ #15a on folder-specific template files. lib/html/exmh-faq.html: Added FAQ #23 on keeping sender's address from appearing in the cc line, written by Pete Gelbman . cvs repository 06/21/2000 Bruce A. Mah lib/html/custom.html: Updated "Preferences Sections" and "Code Organization". cvs repository 06/21/2000 Valdis Kletnieks lib/main.tcl - fix MH version for UCI MH users - was using bogus variable cvs repository 06/20/2000 Bruce A. Mah lib/fdisp.tcl, lib/find.tcl: Add a preferences item to allow finds (control-s in default bindings) to start either in the FTOC or the current message. Patches from John Klassa . cvs repository 06/20/2000 Brent Welch lib/exec.tcl: Put catch around the unsets of ExecCache. Errors can occur in Pgp_Exec_Init if the path to PGP is wrong. cvs repository 06/16/2000 Bruce A. Mah lib/html/exmh-faq.html: Add FAQ #22 about giving preference to displaying text/plain over text/html. Fix minor HTML glitch in FAQ #21. exmh.CHANGES: In a fit of anal-retentiveness, fix a typo. cvs repository 06/16/2000 Brent Welch (By way of Jacob Morzinski) lib/extrasInit.tcl, lib/faces.tcl, lib/flag.tcl Generalized the "slow display icon" preference item to give control over using color icons for the Exmh desktop icon as well as for the faces icons. cvs repository 06/16/2000 Valdis Kletnieks lib/app-defaults - missed a PGP menu lib/pgpBase.tcl, lib/pgpExec.tcl, lib/pgpMain.tcl - handle missing "pattern" which caused PGP 6.5 to not list private keyring. lib/pgpMain.tcl - after changing PGP version in sedit, wrong PGP version used in 'select key' dialog. cvs repository 06/15/2000 Valdis Kletnieks lib/main.tcl, lib/sedit.tcl, lib/seditMime.tcl - output MH version as well as Exmh on X-Mailer: line lib/pgpExec.tcl, lib/pgpGpg.tcl, lib/pgpPgp65.tcl - make PGP Comment: line track the Exmh version actually used... cvs repository 06/12/2000 Brent Welch sedit.tcl: Fixed auto-sign bug having to do with {$t} in app-defaults. Makefile, exmh.install, exmh.README, html/index.html, html/software.html Rationalizing version number to 2.2 Released exmh-2.1.2 6/8/2000 Brent Welch cvs repository 06/08/2000 Valdis Kletnieks Support for PGP 6.5. Added new file lib/pgpPgp65.tcl. Added PGP 6.5 config to lib/pgpBase.tcl, lib/extrasInit.tcl, exmh.install, lib/app-defaults, and lib/html/PGP.html. Fixed a check in extrasInit - it assumed a PGP version was present if the $pubring and $path for the version were there. I added a check that the 'pgp verify' command was present. Otherwise it thinks that 5.0 is available if 6.5 is present. lib/pgpWWW.tcl - provide a working default URL. cvs repository 06/08/2000 Hal DeVore lib/extrasInit.tcl: Corrected help text for Play Multiple cvs repository 06/08/2000 Hal DeVore lib/extrasInit.tcl: Clarified wording of help for Play Multiple Also added help about globbing for sound file paths lib/mime.tcl: nearly lost this change from Christopher Hall: proc MimeParseSingle reads the first line of the body _before_ Mime_SetFileEncoding is called; therefore the first line is in the default encoding for the file (guess this is us-ascii). The first line of the display will be in the wrong encoding. cvs repository 06/07/2000 Scott Lipcon misc/RPM/: added and fixed 2.1.2 RPM generation lib/sound.tcl: added ~ glob to sound file paths (untested) Forgot to update exmh.CHANGES, sorry :) cvs repository 05/30/2000 Bruce A. Mah lib/seditMime.tcl: Fix a bug introduced in last commit to this file; when creating a multipart message, don't assume where the separator is, just scan for it. cvs repository 05/09/2000 Valdis Kletnieks exmh.TODO: remove following 2 patches from #25, add RFC2646 as #50 Also, removed line item 8, it was already in the CVS tree.. lib/inc.tcl: add preference item for 'flist-at-startup' lib/exwin.tcl, lib/widgetText.tcl: add preference item for automatically scrolling to next message cvs repository 05/08/2000 Valdis Kletnieks lib/html/software.html Document Tk/Tcl 8.3.1 lib/uri.tcl Merge in minor fix from Hal Devore, lost somewhere around 2.0epsilon lib/main.tcl Timestamp the logfile cvs repository 05/08/2000 Brent Welch lib/app-defaults, lib/sedit.tcl: Restored the use of { } in the Sedit app-defaults values so we can tolerate spaces in the drafts folder name. Changed the uses of "eval list" to "subst" in sedit.tcl so the bracing trick works in those cases. lib/html.tcl, html_images.tcl: Added an option to disable image loading in HTML lib/html/guide.html: fixed minor typos. cvs repository 04/19/2000 Brent Welch lib/ftoc.tcl, lib/folder.tcl: Added Ftoc_LastFolder and Folder_Previous so you can go back to the folder you were just in. lib/flist.tcl: Added "force" argument to Flist_FindAllFolders lib/folder.tcl: Added Folder_CheckPointShared, Folder_IsShared, Folder_FindShared to support the notion of folders shared by other exmh users. lib/mh.tcl: Changed to use mhProfile(sendproc) instead of "send" lib/msg.tcl: Added call to Folder_CheckPointShared lib/seditMime.tcl: Tweaks to handle proper positioning of the insert cursor. One for --- header separators, another for when you delete the last character in a part. lib/seditQP.tcl: Took out extra Mime-Version header cvs repository 04/19/2000 lib/html/software.html nmh 1.0.4 is out - vkletnieks cvs repository 04/18/2000 lib/seditExtras.tcl Add better support for composing RFC2017 URL external-references Still need to add better support for displaying them - vkletnieks cvs repository 04/18/2000 lib/app-defaults, lib/scan.tcl, lib/seditBind.tcl Handle embedded blanks better - vkletnieks, patch by Jacob Morzinski cvs repository 04/18/2000 lib/PgpDecryptExpect, lib/PgpExec.tcl, lib/pgpGpg.tcl, lib/pgpPgp5.tcl Use ASCII quote character - vkletnieks, patch by Jacob Morzinski cvs repository 04/05/2000 lib/html_head.tcl, lib/html_links.tcl - Use app-defaults c_link, c_alink values for links. - vkletnieks cvs repository 03/29/2000 Updated lib/html/software.html - note *actual* latest versions, removed some dead mirrors, and added a note that nmh 1.0.3 is recommended due to security issues. -vkletnieks cvs repository 03/23/2000 Some work on the FAQ a) Added new question 2c, dealing with RFC2047 encoded headers, with a cross-reference under question 18 (FTOC). b) Did some minor markup changes to question list c) Did some markup revisions to 14 (mailing lists). Also added pointer to mailing list archive and info on digested exmh-user list. d) Markup revisions and additional info in question 15 (templates). It noted 4 types of templates but only listed 3. Now it has info on 4 MH plus 1 new nmh template. -haldevore cvs repository 02/29/2000 Applied patch to speed up pick -Dick Wesseling via haldevore Applied patch to allow parentheses in address book entries -Mats Bengtsson via haldevore Applied patch to limit encodings to one for which we have fonts -Marc Boucher via haldevore Happy leap century day! cvs repository 02/02/2000 Fixed hard-coded '-wrap word' -vkletnieks cvs repository 02/02/2000 Fixed hard-coded 'config -cursor xterm' -vkletnieks cvs repository 02/01/2000 Fixed regexp for glimps version detection -vkletnieks cvs repository 12/6/1999 Added character encoding support to LDAP lookup -iko cvs repository 12/2/1999 Applied Burkhardt patch for specifying POP host with -host flag Fixed "double page up" bug in HTML by eliminating redundant bindings Tweaked error message in install.tcl cvs repository 11/08/1999 Roll back 11/04/1999 bug fix and re-implement it in a different way. -kchrist cvs repository 11/05/1999 Removed app-defaults assumption of PGP use when treating multipart/signed or multipart/encrypted -kchrist cvs repository 11/04/1999 Disable PGP sign and/or encrypt when doing a redistribute. -kchrist cvs repository 10/29/1999 Fix bug introduced with previous PGP options change. -kchrist cvs repository 10/28/1999 PGP options were not being preserved on a re-edit. Fixed a crash when not-enabled PGP versions were selected in sedit. -kchrist cvs repository 10/27/1999 Quick application/pgp support fix. -kchrist cvs repository 10/25/1999 Added a dropKeys pattern to pgpGPG.tcl. Simplified PGP GUI by removing "detached" signature option. Problem was that MIME+standard includes a copy of the message being signed in the signature attachement. What really should be used is MIME+detached. Decided to overload the meaning of "standard". If the format is plain, standard means "binary". If the format is anything else, standard means "detached". Less flexibility but better chance of "doing the right thing". -kchrist exmh-2.1.1 Released, 10/15/1999 cvs repository 10/12/1999 Fixed a bug that caused a new sedit window to bomb if the PGP selection for new windows was not supported. -kchrist cvs repository 10/07/1999 Changed documentation string for quote file name to indicate it is created relative to the exmh startup directory. Fixed a bug in sign+encrypt processing when composing a MIME message. Added a couple of bugs to the list to remind me of what still needs to be done. -kchrist cvs repository 09/29/1999 Fixed a bug in the shorten output processing of GPG. -kchrist cvs repository 09/27/1999 More PGP changes. Consolidated passphrase entry to sedit field or pgpExec routine. Made the pgp-sedit field aware of pgp(keeppass) and pgp(echopass). Moved pgp(keeppass), pgp(echopass) and pgp(grabfocus) to PGP General Interface. Fixed a minor bug left over from my previous GUI changes. -kchrist cvs repository 09/22/1999 Changed the PGP interface, basically the stuff under the Crypt... button. The hope is that the change will help make the different sign options a bit clearer - kchrist exmh-2.1.0 Released, 9/17/1999 cvs repository 09/17/1999 Fixed RPM build, and added spanish support to the RPM, thanks to Francisco Monserrat -slipcon cvs repository 09/15/1999 Typos in getnews.tcl - cwg cvs repository 09/03/1999 Allow (again) spaces in address search strings. (addr.tcl) - kchrist cvs repository 09/01/1999 Fixed text/plain to application/pgp hack in mime.tcl so it ignores the format parameter of text/plain. -kchrist cvs repository 08/25/1999 Fixed some problems with not timing out PGP subkeys (e.g. DSS keys for PGP5/GPG). --bmah. Eliminate last vestige of PGP passphrases showing up in debugging logs. --George Ross via bmah. cvs repository 08/24/1999 Importing keys from email keyserver queries now works. Attaching keys to an email message is now RFC 2015 compliant (content-type: application/pgp-keys instead of application/pgp). --Kevin.Christian@lsil.com via bmah. Made reply-to-all invoke repl -group if repl claims to support a -group flag (i.e. is nmh). Adapted from Debian 2.0.2-7 package. (iko) cvs repository 08/22/1999 Fix a few bugs related to email PGP querying (queries now can go out). Use Exmh_Status to let user know what's happening during an email query. --Kevin.Christian@lsil.com and bmah. Sanitize PGP info out of debugging logs. --George Ross via bmah. Delete More...->old PGP->Encrypt cascaded menu, due to apparent lack of need for this functionality and difficulty in getting it correctly implemented. --bmah. cvs repository 08/19/1999 Change address book expansion to NOT insert new header lines as this broke the "continue lookup" feature. Also changes to allow address expansion on ANY header line (doc changes still to be done). -Kevin.Christian via haldevore cvs repository 08/17/1999 PGP without seditpgp works again. -bmah Wheel mouse support added, enable it in the Windows + Scrolling dialog. - slipcon cvs repository 08/13/1999 Don't try to coerce text/plain PGP messages to application/pgp unless PGP is actually enabled. --bmah Really fix problems with 8-byte GPG keyIDs and keyservers this time. --Kevin.Christian@lsil.com, via bmah Rudimentary support for LDAP --Jason Day and cwg If we ask the user for help in picking the PGP key to use for a receipient and they cancel the resulting dialog, generate an error (instead of asking the user ad infinitum). --bmah cvs repository 08/12/1999 Fix a number of key/passphrase management problems: pgpsedit now manages PGP versions, keys, and passphrases on a per-window basis. Decryption now works when no passphrases are cached. One timeout parameter controls passphrases for all PGP versions. seditpgp UI slightly modified. --bmah Get rid of "PGP Preview" menu item in sedit left over from debugging. --bmah cvs repository 08/10/1999 Properly use [Env_Tmp] in the below patch -cwg Ignore high-order bytes of key IDs returned by GPG for compatability with keyservers. --bmah Properly process PGP/MIME messages that have boundary characters containing regular expression special characters. --bmah cvs repository 08/05/1999 Prompt before executing buttons on html pages which are either non-local or in /tmp. -cwg cvs repository 08/04/1999 Fixed problems with not providing a password under pgp2 -cwg Renamed the *.n.html pages and rephrased links to them -cwg Got passphrase timeout to work yet again -cwg cvs repository 08/03/1999 Display the body of a message which fails to be decoded by PGP. -cwg Finished User Interface
There are many knobs and dials you can adjust to control the behavior of exmh.
URL Smarts
Exmh can scan for embedded URLs in your messages, and it can look for X-URI: mail headers. These are turned into active text buttons. Click on them and exmh asks your favorite Web browser to display the URL.
User Programming
If the preference settings are not enough for you, you can program exmh more directly. You can define new buttons and menus and add new Tcl code to its implementation. This is described in here.

GETTING STARTED

Mostly likely you are already an MH user. If not, go through the tutorial.

If you previously used a mail reader like Elm or Sun's mailtool that manages mail folders in mbox-like files, then you can use the menu entry to copy your old folder contents into the folders manage by MH and exmh. This menu entry is under the folder More... menu.

There is an extensive system for exmh that lets you tune it in many ways. Throughout the man page, references to settings will be made when there are tunable parameters associated with a feature. A more complete description of the facility is given onn the custoization page.

KEYBOARD COMMANDS

Several of the folder and message operations have keystroke bindings so you can do much of your browsing with hands on the keyboard. The default bindings are defined with the Tk syntax that you'll need to use in the Bind dialogs. Capitalization is important. For more information, see here. You can browse, change, and define new command keystrokes via the Bind user interfaces available under the Bindings menu. There are two dialogs: one for editing commands in the built-in editor, and another for the command bindings described above.

THE EXMH DISPLAY

At the top of the display is a sub-window that has a label for each of your top-level folders. In the middle there is a table of contents for the current folder. At the bottom the current message is displayed. Both the folder display and table of contents have some highlights that are described below.

The command buttons are grouped into three sets. The buttons along the top apply to exmh itself, such as Help..., , and . The buttons above the scan listing are operations on folders, like and . There is a menu there labeled More... that has several more folder-related operations like and Sort.... The row of buttons above the message display are for operations on messages, such as , , and . There is another menu here labeled More... that has several more operations on messages, such as , , and .

The version number of exmh is displayed next to the top row of buttons. The release cycle for exmh goes something like 1.5alpha, 1.5beta, 1.5gamma, ... 1.5, 1.6alpha, and so on. The unqualified versions are deemed "stable" enough for naive users.

Summary information for the current folder appears next to the folder buttons. This indicates the current folder and how many messages are in it. Just below the scan listing is a status line that provides some feedback about what exmh is doing. When a new message is displayed, the subject or Content-Description component is displayed there. Just to the left of this the folder and number of the current message is displayed.

To the left of the message buttons the EXMH logo appears. This is replaced with the facesaver image of the person, or their organization, that sent the current message.

The black diamond to the right of the status message area is a grip that you use to change the boundaries between sub-windows. The resize unfortunately depends on heuristics based on the size of text being displayed in the window, so you have to have a message displayed before the resize will work.

Press the first mouse button on the black diamond and a horizontal line appears. As you drag the line up and down, the status message indicates what boundary you are changing. Initially you are adjusting the scan listing (middle sub-window). If you drag the line off the top of the scan listing, the mode changes and are now adjusting the folder cache size, if it exists. If you drag the line above the folder cache, the mode changes again you are changing the main folder display area. As you drag the line down, the mode changes again. The main drawback of the automatic mode sensing is that you cannot grow the main folder display area by more than the size of the folder cache, if it exists.

There are also preference settings for each of the sub-window sizes. Look under Scan Listing, Folder Cache, and Folder Display .

FOLDER DISPLAY

The top sub-window has a label for each of your MH folders. The folder display is highlighted to reflect the state of folders. The menu item under the main Help menu will display a key for the highlights.

black - the current folder. bold outline - a folder with unseen messages. stippled background - the target folder for move and link operations.

On color displays:

red - the current folder. blue - a folder with unseen messages. yellow - the target folder for move and link operations.
Folders that have nested folders under them are highlighted by a shadow box.

The mouse bindings for the folders labels are:

Left - Change to folder. Middle - View nested folders. Right - Refile current messages to the folder. Shift-Right - Link current messages to the folder. Shift-Middle - Drag a folder label to some drop target. Control-Right - Clear the current target folder.

Note that a right click does two things at once. It selects the target folder for refile, and it marks the currently selected message(s) for pending refile to that folder. This might seem over-eager at first, but it is quite useful once you get used to it. The currently selected target folder remains highlighted, and you can move a message to this folder by clicking the Move button or typing 'm'.

A middle click on the folder label displays a pop-up window with the folder labels for nested folders, and you can operate on these labels just like the top-level ones. The pop-ups work recursively for nested folders. When the mouse leaves the pop-up it is withdrawn. The Folder Display lets you adjust how the pop-up behaves.

Hint: If you change the pop-up-related settings, you'll have to resize the exmh window a bit to force it to redisplay the folder labels. Only then will the new bindings take effect.

You can make the folder display into a separate top-level window with a setting under the Folder Display . This means you can close the main window and still view the folder display to see what folders have new mail in them. When you click on a folder label the main window will be opened automatically.

FOLDER CACHE

Below the main folder display is a cache line of recently visited folders. If you have nested folders, their complete pathname is given in the cache window. Using the Folder Cache settings you can choose how many lines of folder cache. You can also put some folders into the cache permanently with the Sticky Folders preference item.

If you don't have many folders, the folder cache line is really just a waste of screen real estate. In this case, set the number of folder cache lines to 0 in the Folder Cache section to eliminate this part of the display altogether.

You can drag folders in and out of the folder cache. Use <Shift-Button-2> to drag a folder label. Drag a label from the main display into the cache to add it, or from the cache to the main display to remove it from the cache.

FOLDER TABLE OF CONTENTS

The middle sub-window lists the messages in the current folder.

The lines of the scan listing are highlighted to reflect the state of each message. On color displays:

Red - the current message. Blue - unread messages. Grey background - messages marked for deletion. Yellow background - message marked for refile to another folder.

On monochrome displays:

Reverse video - the current message. Underlined - unread messages. Cross-hatched background - messages marked for deletion. Stippled background - message marked for refile to another folder.

The mouse bindings for the scan listing are listed below. "Drag" refers to holding the mouse button down while moving the mouse.

Left - select and display a message. Left-Drag - select a range of messages. Shift-Left - modify the selected range. Middle-Drag - scroll the display. Right - select but do not display the message. Shift-Right - Drag folder/msgID to drop target.

Several of the operations on messages can be applied to a set of selected messages. You can create a discontinuous selection by using the Shift-Left (and Shift-Left-Drag) mouse actions.

Hint: The scan listing comes from both the MH scan and inc programs, depending on circumstance. If you define a custom scan format, set the same filter in your profile for both inc and scan.

MESSAGE DISPLAY

The current message, if any, is displayed in the bottom sub-window. The uninteresting mail headers are scrolled off the top of this display initially. You can control this with the Header-Display and Header-Suppress profile entries as described on the customization page. That page also describes how to colorize different mail headers.

Pressing the space bar will page you through the message, or take you to the next message if you are at the end of the current message. Backspace will go back a page. You can also scroll the message with the mouse by using the scrollbar or drag-scrolling.

MIME messages are indicated by displaying their content-description in the status line. The mouse cursor is changed to a watch while the MIME message is parsed and displayed. On a color display, a MIME message body is displayed in a slightly darker background. This shading is used to indicate the depth of nesting in a multipart MIME structure.

A pop-up menu is available to process MIME messages, such as saving their contents or processing the contents with an external viewer. Press the right mouse button in the message display area to obtain this menu. Make sure you press the mouse button over the message body, not the headers. For multipart messages, the menu changes depending on what part of the message you are looking at. See also the entry for MIME for some parameters you can adjust.

Every content type can be saved or printed, and other types can have additional options depending on entries in your site's mailcap file. The print function just prints the item as text using your Print command. The print-with-mailcap entry, if available, uses the print command as defined for the content-type in the mailcap file.

You can display a message in a new top-level window in order to save it around on your display. Use the Clip operation under the message More... menu. This will display the current message in a new, larger window.

Exmh can cooperate with a WWW browser to display web pages. If you get a URL in a mail message, then use the 'z' keystroke to highlight the URLs in the message. (This is ad-hoc and not %100 accurate.) The URLs are turned into active text buttons. Click on one and exmh asks your web browser to display the page. You can have exmh scan every message automatically for URLs, although this can be slow. Tune this with the settings under the WWW .

If exmh sees special X-URL (or X-URI) headers it will turn the facesaver area into an active button. It takes on a raised relief and when you click on the face (or exmh logo) then the web browser is asked to display the URL in the X-URL header. More and more folks are putting X-URL headers into their mail messages so you can find their home page.

MAILING LIST SUPPORT

If messages on a mailing list contains headers compatible with RFC2369, exmh will provide an additional menu called "List..." for the messages with mailing list specific options. These options may include (but are not limited to):

  • help
  • subscribe
  • unsubscribe
  • post
  • archive
  • owner

These options may bring you to a web site or may put you in email composition mode.

Evangelism about the usefulness of this functionality to mailing list managers would be appreciated.

MANAGING MESSAGES

There are three basic actions you can take with a mail message: leave it alone, delete it, or refile it to another folder. You automatically advance to the next message after you delete or refile the current message. This makes it easy to go through your mail messages, deleting and refiling as you go. There are several settings under the Scan Listing section that control the behavior of exmh when reading mail, and some of these will be mentioned below.

Like xmh, exmh does deletes and refiles in two steps. In the first step you mark a message as needing some action. Later on you commit these changes by pressing the Commit button, or by pressing <Control-Return>. Unlike xmh, however, exmh requires that you commit changes before you view a different folder. Marked messages are highlighted in the scan listing, as described above. If you reselect a message marked for refile, the destination folder for that message is shown in the Status line.

Deleting Messages. To delete a message, use the Delete button or press 'd'. Delete results in a call to rmm. If you want deleted messages to be refiled into a special folder (e.g. +wastebasket or +deleted), you'll have to define a shell script and register that as your rmmproc in your .mh_profile.

Trick: If you press 'D' to delete a message, then you advance to the next message without displaying it, so you can quickly go through a folder to clean it up.

Refiling Messages. To refile a message, right click on the destination folder. This marks the current message(s) for refile to that folder, and leaves the folder selected as the current target folder. If the right target is already selected, then you can use the Move button or type 'm' to refile the message and advance to the next message.

Trick: If you press 'M' to refile, you advance but do not display the next message.

Undo. If you make a mistake, you can unmark a message with the message More... menu entry. This operation applies to the currently selected message(s), not necessarily to the last message you marked for delete or refile. If you want to change the disposition of a message, like refile it instead of delete it, you do not need to unmark it first. Just select it and take the new action.

Trick: use '-' (minus) to back up to a message you just marked, and 'u' to unmark the message.

Linking Messages. To link the current message(s) into a folder, hold the shift key down as you right click the destination folder label. If the right folder happens to be selected as the target already, you can also use the button. If you use Link frequently, you should adjust the Scan Listing item for Advance after Link. If you turn this off, then the current message remains selected after a Link, which makes it easier to link a message into multiple folders.

Auto Commit. The Auto Commit Scan Listing item will let exmh commit your changes when you change folders, sort or pack a folder, or quit the program. Without auto commit, you will be prompted to commit when you try to take one of these actions and have messages still marked for delete or refile. In addition, auto commit will commit changes when you close the main window.

Implied Direction. The next message viewed after a or is usually the next message. However, if you set the Implied Direction preference item, then exmh will remember your last or action and move that direction after a or . This means you can just as conveniently go through a folder backwards as forwards, although it might catch you by surprise.

Skipping Marked Messages. The skip marked msgs item controls whether Next and Prev take you to a message marked for delete or refile, or whether you skip over these. Remember the handy '-' key binding, which takes you to the previous message even if it is marked.

Changing Folders Automatically. When you are at the end of a folder, exmh will be ready to take you to the next folder that has unseen messages in it. You can just press Next, and it will automatically change folders for you. If you have marked messages, however, you will be reminded of that. At this point you can press the button, or if you have auto-commit enabled, then you can press the button again to trigger the commit and folder change. If you always want to be warned before an automatic folder change, enable the Next Guard item. With this enabled you will have to click twice (or type 'n' twice) to get the automatic folder change. It will also tell you to which folder it is about to change.

The final twist on automatic folder changing is that, by default, exmh will automatically change back to your "first" folder if there are no more folders with unseen messages in them. You can disable this feature with the Cycle back to first item. The default Folder-Order profile component defines inbox to be the first folder, so ordinarily you will change back there. The Folder-Order profile component is described in the customization page.

SENDING MAIL

This section describes how to start a mail message. The messages are created as templates in your drafts folder and then your editor is opened on the draft. The next two sections describe how to actually compose the message when using the built-in editor or an external editor.

Sending a New Message. Use the message button to create a new draft message. This runs the MH comp command to set up the template for the draft, so it is affected by your components file, if any, and your comp profile entry, if any.

Replying to a Message. The Reply... menu has two entries: and . These use the MH repl command, so they are affected by your replcomps file, if any, and your repl profile entry, if any. The first entry uses -nocc to -nocc cc so that the reply just goes to the sender and you, while the other entry uses -cc all so that the reply goes to everyone in the To and Cc headers of the original message. There is also an entry that displays instructions for adding more entries to the Reply... menu. This is described in more detail on the customization page.

Forwarding a Message. Use the button to forward the current message, or messages. This uses the MH forw command to set up the message, so it is affected by your forwcomps file and your forw profile entry, if these exist.

Using an Existing Message as a Template. You can use an existing message as a template for a new message by using the menu entry under the message More... menu. In this case the message is copied into the draft folder first. You will also use this menu entry if you have to go back into your drafts folder to continue work on a message draft.

THE BUILT-IN EDITOR

The built-in editor provides a handful of text editing commands and several operations that affect the formatting of a mail message.

Sending a Message. Usually all you need to do is fill in the headers of your message, type in the message, and press the Send button. When you start, the cursor will be positioned at the end of the first empty header line, or at the beginning of the message body if, as with reply, all the headers are already initialized. When entering the headers, <Tab> will take you to the next header line, and <Double-Tab> will position the cursor at the start of the message body.

The only important rule to remember about mail messages is that the header and body are separated by a blank line. In addition, MH supports a header separator line of all dashes, ------.

Saving a Draft. If you want to save a message draft and return to it later, use the Save&Quit button. If you want to send a message but save it for use as another draft, select the Keep on Send check-box item under the More... menu. In this case, when you click Send the editor will remain open and the message will remain in your drafts folder. Otherwise the draft message is removed from the drafts folder after it has been successfully sent. (Actually, it is renamed in the same fashion that rmm renames deleted messages.) If you quit exmh and you have drafts in progress, they are automatically saved and remain in your drafts folder.

Warning! the Save button under the More... just writes the editor's buffer to the file system. It does not imply that the draft will remain after it is sent. You probably want Save&Quit or Keep on Send instead.

Aborting a Draft. If you decide you do not want to send a message, you can delete it by pressing the Abort button. If you have not changed the initial template it will be aborted immediately. Otherwise it will prompt you for confirmation.

Trick: a second click on the Abort button is the same as clicking the OK button in the confirmation dialog.

Signatures. The editor supports signatures in two ways. If you select Auto-sign from the Simple Editor section, then your .signature file will be appended to the message when you press the Send button. Otherwise, you can use the Sign button to insert your .signature file at the end of the message.

If you have several files that match the pattern ~/.signature*, then you will have a menu of signature options available under the Sign... menu, which replaces the Sign button. You can define the default choice with a Preference setting under the Simple Editor section. With auto-sign, the Sign... menu has a set of check box items that determine which signature file will be used. Otherwise, the menu simply selects which signature you want to insert at the end of the message, and the signature is inserted when you select the menu entry. If you are composing a multipart MIME message, your signature is added as another MIME part.

When auto-sign is enabled, a further option on the Sign... menu allows "intelligent" signing of messages. This means that messages which are sent solely to addresses within the local domain can be signed differently from messages being sent outside of it. The Intelligent Signatures section allows you to specify two different files, one as the local signature file and one as the external signature file, along with a list of domains to be considered "local", and the default state of the intelligent sign menu option.

Trick: if your signature file has the execute permission set, then exmh will try to execute it and use its output for the signature. (If you accidentally have the execute bit set, the error that occurs may not be that clear). In this case, three arguments will be passed to your signature file (in this order): the composition method used for that message (i.e. one of [comp, repl, forw, dist, unknown]), the name of the current MH folder when composition was started, and the absolute pathname of the draft message. You can then use these to decide on a suitable signature to output.

MAIL FORMATTING

Line Breaks. By default, you can just type in long lines and they will wrap at word boundaries when the line gets too long. This actually happens twice, the first time by the Tk text widget when you enter text. Unfortunately, this doesn't actually insert newline characters, and it is done based on the size of the window. Therefore, the line breaking is done a second time by exmh after you press the Send button. The line length limit defaults to 79, although you can change that in the Simple Edit section.

Hint: If you change the line length, you should also resize the editor window to match the width (e.g. 72) so your message will look right as you type it in. Set the following resource in your ~/.exmh/exmh-defaults:

*Sedit*Text.width: 72

Changing Fonts. You can use the Text... menu to change the font of the selected text. This promotes your message to a MIME content-type of text/enriched. The encoding of these text looks is also done when you press the Send button. You may see the encoding after clicking Send as a side-effect of the way this is implemented.

The Insert File... menu entry is used to insert a file as-is, with no MIME structure. The file is inserted at the current insert point in the editor.

The Quote... menu is used to quote the message you are replying to. This menu is only enabled when you are replying to a message.

The Quote menu entry formats the replied-to body a little, just by prefixing each line of the message body with a string. The default is "> ", and you can change this via the Simple Editor section.

The Quote menu entry produces a mime attachment which contains the replied-to message.

Note: it is apparently not possible to define a repl prefix with leading spaces. This is a side effect of storing the prefix in the X resources database.

The Cite Selection menu entry formats and inserts selected text. It is assumed that the text is from the current message, and the sender of that message is identified just before the inserted text. You can use this feature to insert text from several different messages.

The Crypt menu provides access to the Pretty Good Privacy public key system. With this you can send messages with a digital signature that certifies that you sent the message. You can also encrypt and decrypt messages with PGP. A complete discussion of PGP is far beyond the scope of this page. However, if you know PGP, you will find the PGP features of exmh useful.

Hint:. The Insert PGP Keys menu entry is hiding over in the Sedit More... menu. Use this to insert your public key or other public keys into a mail message. By default, only your keys are listed in the key chooser. Just type in part of the key ID of any key you want to choose and matching keys are displayed. Try '*' to list all keys.

MIME FORMATTING

Warning! The line-break formatting described above can interact poorly with the formatting described next. This is one of the roughest spots in the exmh implementation. For example, if you include a file in your message that has important formatting, like a Postscript file or some program code, you will want to disable the line-break formatting. You can do this by turning off the Format mail check-box item under the More... menu.

If you are familiar with mhbuild directives, you can enter them into your message. In this case, you will want to select the Attempt mhbuild check-box menu item under the More... menu. Again, you will probably want to disable Format mail to make sure that long mhbuild directives are not chopped into multiple lines at the wrong place.

You can create a multipart MIME message by using the Insert Part... menu item. This adds another part to your message, promoting it to MIME content-type multipart/mixed if necessary. The first time you add a part, you have the option of preserving the existing message body or completely replacing it. When the file is inserted you are asked to choose its MIME content-type and content-transfer-encoding.

The Insert External... menu entry is used to create a MIME part of Content-Type message/external-body. This is an indirect reference to a file, which is either a local file or a file available via anonymous FTP. A dialog lets you fill in the various parameters to the indirect reference. For an anonymous FTP pointer, the Site is the Internet host name and the Directory and File name determine what file it is. The Transfer mode is either "text" or "image". Use "image" to ensure that all 8 bits of each byte get transferred. The Description is for the benefit of the receiver of the mail message and should describe what the pointer references.

Trick: A file section dialog appears first, but this is not always appropriate if you are making an external reference to a non-local FTP site. Just hit cancel on the file selection dialog. Then, when you enter the file name, the content-type will be inferred from the name. You can always override the content-type if exmh guesses wrong.

8 BIT CHARACTERS

The built-in editor supports 8-bit characters found in European character sets. Insert an 8-bit character by pressing the Compose key and then two other keys to get the special character. For example, Compose, then e and ' creates an accented e character. All the vowels can be composed with ' ` and " to get accents, and there are several more bindings. The complete table of compose key sequences is given by the entry in the Bindings... menu.

When you compose a mail message that contains 8-bit characters you need to be careful when sending it. Some mail gateways do not like 8-bit characters and will bounce the message or corrupt it. The Quoted-Printable encoding will protect 8-bit characters. The built-in editor will do this quoting for you if it detects input of an 8-bit character. The quoting is done when you press Send. You can control whether or not this happens with a combination of the Quote Printable menu entry (for per-message control) and the Quoted Printable default preference item for the Simple Editor.

The built-in editor handles the special coding required when including 8-bit characters in mail headers.

When you are replying to a message that contains 8-bit characters, it may be encoded, too. The Quote operation will first decode the message so that the true 8-bit characters are inserted into the editor buffer. This works better than the repl filters that include the message body. If you use one of those, then you'll see the quoted-printable encoding instead of the 8-bit character.

USING ANOTHER EDITOR

You can use your favorite editor with exmh by specifying an Editor command in the Editor Support section. This command has the complete pathname of the draft message appended to it before it is executed. Several examples of editor commands include:

sedit mxedit emacsclient & gnuclient & exmh-async emacs exmh-async emacsclient exmh-async gnuclient exmh-async xterm -e vi
The built-in editor is called sedit. Mxedit and tkvi are Tcl-based editors that know how to communicate with exmh about draft messages. emacsclient is a program that is used to communicate with a running emacs in order to get it to edit a specified file. You will need the "server.el" package for emacs in order to set up your emacs as a server for this arrangement. There is more information about this in the misc directory of the exmh distribution. emacsclient can used in two ways. If you can post the message directly from emacs, then just use "emacsclient &" and exmh forgets about the draft and assumes emacs will take care of it. Otherwise, use the exmh-async wrapper that is described below.

After the editor exits you are presented with a What Now dialog that gives you several options: Send, Abort, Save, Re-edit, and More... Under the More.. menu you can apply mhbuild, run a spell checker, or run the MH whom program to verify the addresses you have specified. You can also invoke the built-in editor, sedit, in case you want to use its MIME composition features.

There is an "Alternate Editor" setting. The built-in editor has a menu entry that saves the draft and starts the alternate editor. The What Now dialog also has a menu entry to do this.

In most cases you will use the exmh-async wrapper script to run an external editor. This is a short Tcl/Tk script that runs your editor and then communicates with exmh when your editor exits. This means the exmh user interface can remain active while you compose your message. You can even compose several messages at once. You will get a different What Now dialog for each message draft.

The exmh-async wrapper tries to pass through all the arguments to the editor command you specify. However, a couple arguments are picked up by the Tcl/Tk shell (wish). Some tricks are played, however, so you can protect arguments. For example, the following works:

exmh-async xterm {-geo 80x40+0+0} -e vi {+c /: *$}
This protects the -geo argument from exmh-async, and it protects the complex format of the vi search command from interpretation by the Tcl parser.

As a final note, if you try to test exmh-async from the command line, you need to execute it like this:

exmh-async exmh xterm -e vi &
The first argument is the name of the exmh application, which is needed for the Tk-based communication between exmh-async and exmh. This argument does not appear when you define the command in .

FILTERING MAIL

One of the strong points for exmh is its support for mail filtering systems that file messages into different folders as they are delivered. The filtering is done by looking for patterns in the mail headers. For example, you can put all the mail from your boss into one folder, and all the mail from a mailing list or digests into another folder. Exmh visually highlights the folders that have new mail. This depends on the definition of the Unseen-Sequence profile component, and the support of this sequence by the mail filtering system. Both the slocal and procmail filtering systems use the rcvstore program that takes care of these details. The inc program also adds messages to the unseen sequence, so even if you do not filter mail the new messages in inbox will be highlighted by exmh.

The standard filter used with MH is described in the mhook (or slocal) man page. Below is a quick summary of how it works. You must maintain a file named ~/.maildelivery that has your mail filter specifications. The contents of the file are explained below. If you can forward mail into programs at your site, then put this into your .forward file to get filtering:

| /usr/local/mh/lib/slocal -user yourname

Alternatively, if you select the "presort" inc-style described below, then exmh will run slocal for you each time you say .

If you use the procmail system, or perhaps supply your own, use the MH rcvstore program to put messages into folders. This program updates the unseen sequence so exmh can find the new mail. Unfortunately, the rcvstore program is in the MH library, so you must reference it with a long pathname, (e.g., /usr/local/mh/lib/rcvstore.)

A sample .maildelivery filter file is shown below. Note: this file is ignored if it has group or world write permission. It uses the rcvstore program to refile messages into different folders. The first field is the header to match, and the second is the value to look for. This is a case-insensitive string. The third column specifies an action. In this case | says to pipe the message into the program in the last column. The fourth column provides limited decision making. In this case the ? means to try and match this filter if the message has not already matched a previous filter. The complete syntax of the filters is given in the mhook man page.

subject exmh | ? "/usr/local/lib/mh/rcvstore +exmh" subject mxedit | ? "/usr/local/lib/mh/rcvstore +mxedit" subject book | ? "/usr/local/lib/mh/rcvstore +book" to journalclub | ? "/usr/local/lib/mh/rcvstore +journal" from footbag-digest" | ? "/usr/local/lib/mh/rcvstore +footlist" default - | ? "/usr/local/lib/mh/rcvstore +inbox"

Warning! If you use the .maildelivery file to filter messages, you should always have a default action in the file that refiles the messages into your inbox (or some catch-all folder). Depending on your local configuration, there might not be a good pre-default default action. If there is no default action, mail that does not match a filter will be discarded!

A patch for the slocal program is distributed with exmh. It adds an additional syntax to the maildelivery file that makes it simpler to use rcvstore. Use the + operation instead of | (pipe) to specify a refile action. The above example looks like this:

subject exmh + ? "exmh" subject mxedit + ? "mxedit" subject book + ? "book" to journalclub + ? "journal" from footbag-digest" + ? "footlist" default - + ? "inbox"

Incorporating Mail. The filtering support affects the way you incorporate mail from your system spool file. Exmh supports several different styles: inbox, multidrop, presort, presortmulti and none. Use the Incorporate Mail preference section to choose one. You may also want to enable periodic inc under the Background Processing section.

inbox
moves new messages into your inbox folder. This is the default. No filtering is done, but the inbox folder label will highlight when new mail is incorporated into it, and unread messages will be highlighted.
none
If you use your .forward file to process mail through an external program in order to deliver messages into various folders, then you don't need Inc in the user interface. Selecting "none" will eliminate the button altogether and disable the internal Inc procedure. A background "flist" task is a nice complement to this setting so that you can see what folders are getting mail.
presort
moves new messages directly into various folders. This is similar to what you may be doing already with an external program. This is built this into exmh in order to eliminate the need for an external program. (I cannot use a .forward file at my site.) The way presort works is to inc from your spool file into a temporary folder (MyIncTmp). Then, the MH filtering hook slocal is run on each message. In this mode, it is expected that the filtering action is to put the message into a folder. You do this by specifying an action that is to pipe the message into the MH rcvstore program. See the MH man page for mhook for details.
multidrop
This assumes that you use POP or the MH maildelivery facilities (see mhook) to put new messages into a set of drop-boxes (inbox-like files). You set up the correspondence between POP hosts and folders, or between inbox files and folders with your ~/.xmhcheck. file. moves messages from the POP server or drop-boxes into folders. The format of each line of ~/.xmhcheck file is shown below. In the first case, the file name must be an absolute pathname (i.e., has leading /). In the second case (POP), the third field is an optional user ID.
presortmulti
This is a combination of multidrop and presort. Any drop-box that is associated with the MyIncTmp folder gets filtered just as with presort.

The .xmhcheck file. The following shows the format of the .xmhcheck file. If the folder_name is MyIncTmp and you use presortmulti inc style, then messages are filtered after they are fetched from the dropbox.

folder_name   /filename/of/dropbox
or
folder_name   POP_hostname [POP_user_name]

NNTP NEWS

Exmh has support for retrieval of unread news messages from user-specified newsgroups via NNTP (Network News Transfer Protocol). It does not have the full functionality provided by a threaded news-reading program such as trn or the gnus package for emacs; however, it can be useful to download news periodically from a small number of low-volume groups within exmh's mail-reading environment. There is also an item on the More... message menu to allow the current message to be posted to a newsgroup.

News retrieval is configured using the NNTP Support section. The machine running your local NNTP server (often called "news") can be specified, along with the port it uses to listen for connections (this is almost always port 119). If your news server requires authentication, you can also specify your username and password. You can specify a whitespace-separated list of newsgroups which should periodically be checked for new news, and you should give the pathname of a file which will be used to store a record of the messages you have already read. Most news-reading programs use the .newsrc file in your home directory for this purpose, so if you want to use exmh as well as another news-reader you should use this filename. Two options are provided for newsgroup moderators to ease the process of posting a moderated message to the group.

In order to enable background news processing, two options in the Background Processing section must be set; one of these enables background news retrieval, and the other specifies the interval at which this should be performed. News retrieval is a relatively time-consuming business, so it is recommended that this interval be no shorter than 60 minutes, and 120 or 180 minutes would be quite reasonable. Note that background news retrieval can be enabled and disabled independently of any background mail-processing option you have selected.

When retrieving news, exmh uses a method identical to the "presort" inc style described in the Filtering Mail section above, i.e. news articles are downloaded into a temporary folder and then the slocal program is run on each one. For more information, see the mhook or slocal man page.

FACES

One of the more fun features of exmh is its ability to display the facesaver bitmap of the person that sent you mail. There are three sources of the images: the facesaver database, inline X-Face mail header fields or inline X-image-url mail header fields. These sources can be used independently, but the main trick is getting exmh configured properly to use them.

Facesaver Database. The exmh installer asks for two pieces of facesaver-related information: the root directory of your faces installation and a search path of faces directories. This assumes that you have retrieved the faces software and associated databases and installed them under on directory, which is referred to as its root directory. The default is /usr/local/faces. Underneath this directory there is assumed to be one or more directories that contain facesaver databases. It is these directories that are named in the search path; the names are relative to the root of the faces installation. Typically there is facesaver, logos, and a local database, which is called parc at my site. The first two databases come from the facesaver.tar.Z and logos.tar.Z files, respectively. The default values are:

Faces Root Directory /usr/local/faces Faces Search Path parc logos news facesaver

If you are setting up your own database, you need to understand how it is organized. It is easiest to demonstrate by example. For myself, welch@parc.xerox.com, my facesaver image is found as com/xerox/parc/welch/face.xbm. Exmh will look for this file under each of the directories named by the faces search path. The complete pathname might be /usr/local/faces/parc/com/xerox/parc/welch/face.xbm. If a bitmap is not found, then the search algorithm trims off trailing components in an effort to find a more general bitmap, typically a company or organizational logo. At your site, for example, you might only have /usr/local/faces/logos/com/xerox/face.xbm, which contains the Xerox corporate logo.

If your exmh installation is not correct, or if you have a personal faces database that the exmh maintainer doesn't know about, then you can also override the install-time settings with the FACEPATH environment variable. This is a more traditional search path of colon-separated directory names.

X-Face headers. The X-Face header contains a compressed version of a facesaver bitmap, which is a 48x48x1 (monochrome) bitmap. The faces software comes with some filters and scripts to generate these and decompress them. The original purpose of the X-Face header is as a way of distributing your facesaver image so that folks can update their database. However, at the moment exmh just decompresses the bitmap and displays it. It requires a Preference setting for the X-Face pipeline for this to work. If the pipeline is blank (the default), no processing is done. To decompress and display the header, use a pipeline setting like this:

uncompface | ikon2xbm
The uncompface program comes with the faces software. It also has a version of ikon2xbm, but a faster version of this program (a C program instead of some scripts) is distributed with exmh in its misc directory. Future versions of exmh will cache the results of decompressing the X-Face line in a personal faces database, but in the current version it just writes the file to /tmp/FACES.[pid]. If you are inspired you could add a Hook_MsgDisplay to stash this file into a real facesaver database. More information on hook procedures can be found here. If you do this, please post your inspiration to exmh-workers@redhat.com.

X-image-url headers. The X-image-url header contains a URL referring to an image. These should be icon-sized.

SEARCHING IN EXMH

There are several ways to search for things in exmh:
Find in message body
Searching uses regular expression syntax, and case is ignored.
Find in table of contents
Searching uses regular expression syntax, and case is ignored. This just searches over what you can see in the display. If you select All, then all matching messages are selected.
Hint: Use the "List only selected messages" folder More... menu entry to get a listing that only contains the selected messages.
Pick by attributes
A general search (i.e, MH pick) over the messages in the folder. This can run slowly because each message in the folder must be processed. You can match on various header fields by using the "Choose pick option" menu in the Pick dialog. If you choose more than one option, the messages must match all of them, unless you use the Not and Or buttons to build up more complex criteria. This interface is explained in more detail in the tutorial.
The "Add to Sequence(s)" option will add the matching messages to an MH sequence. Just pick a meaningful name for the sequence. The "Pick from Seq/msg(s)" lets you narrow the search to a sequence (e.g., "unseen" or something you defined yourself) or a set of messages (e.g., last:100 for the last 100 messages in the folder).
The "All to Sel" option determines if the matching messages are added to the currently selected set, or if a new set is created.
Glimpse full text
Glimpse is a full text searching tool from the University of Arizona. Invoke the "Glimpse full text" menu entry under the Search... menu to bring up an interface to this tool. You must first index your mail, so to get started click "index" to build your indexes. This process runs in the background, and the status of the index process is displayed in the Glimpse log. The storage overhead of the indexes is about 10% to 15%, which is quite good for a full text index system.
To search, enter a word in the search area and press "Search". The button changes to a "Stop" button, although the stop may take a moment to take effect. The search results are displayed in the log. Click on the message in the log and exmh will visit that message.
Glimpse supports approximate pattern matching, so under the Opts... menu you can choose how many errors are allowed in a word match. You can also control if the search is case sensitive or whole word.
Exmh creates one glimpse index per mail folder. These are stored under the ~/Mail/.glimpse directory. This lets you limit the search to the current folder, or to the current folder and its sub-folders.
To update the index, just press index again. If a folder has not changed then the index is not rebuilt. While Glimpse has an incremental reindex feature, exmh does not use it. There appear to be bugs in it.
For more information about Glimpse, see http://glimpse.cs.arizona.edu:1994/.

TIPS

Background Processing
You can set up exmh to periodically incorporate mail (i.e., ) for you. If you already do this via an external agent, then you should have exmh periodically check for new mail in your folders, which is the action. The folder highlighting and icon feedback work best with and . You can also have it periodically run msgchk or count messages in your spool file, but the disadvantage of doing this is that there is no audible or icon feedback when it sees mail waiting in your spool file. Instead, there is just a status message that you might not notice. Choose what background action is taken and how frequently it is done with the Background Processing section. (Background NNTP news retrieval can also be enabled via the Background Processing section, independently of which of the above background actions you have chosen).
Scan Caches
Exmh maintains a cache of the scan output for each folder. If you run MH programs from the command line it can invalidate the cache. You can manually update the cache with the operation under the Folder More... menu. There are also menu entries that update scan caches for all your folders. These run in the background so the user interface can remain active. The scan cache is compatible with xmh.
Performance
If you want message display to go as fast as possible, do three things. 1) Disable the X-Face pipeline command so you do not try to decompress X-Face headers. 2) Disable the facesaver database, which is distinct from the X-Face pipeline. Actually, this is only slow on the first message you receive from a new email address. The pathname of the bitmap image that corresponds to that address is cached to avoid the expensive lookup the next time you view a message from that address. 3) Disable the Graphic Separator in the MIME . That uses a 3D line of text instead of a blank line, and it takes a bit longer to display.

exmh does not like really big folders. If you have more than several hundred messages in a folder you will notice that folder change times get pretty slow. Take this as a nudge to reorganize things into sub-folders. Every three months I move saved messages into sub-folders with names like 94Q2, 94Q3, etc. I understand the performance problems involved, and plan to overhaul some of the exmh internals to improve this situation. In the meantime...

Really big folders with lots of messages in the unseen sequence are really slow. Use the folder More... operation to clear the unseen sequence. You probably want to do this when you import mail from other systems mailboxes.

More Keyboard Stuff
If you really like using the keyboard instead of the mouse, you can change folders, set the target folder, and select messages by number with keyboard commands. When you type plus ('+'), focus warps to the status line so you can type in the name of a folder. In this mode, a plus cycles between choosing the target folder for moves or a folder to change into. <space> does folder name completion, <Return> accepts the folder name, and <Control-c> cancels the folder selection. If you start by typing a number (not plus), that message is selected, but it is not displayed until you press <Return> or "s".

INSTALLATION

Installation is done via the exmh.install script. Invoke it as:
wish -f ./exmh.install
This puts up a dialog box that lets you patch various file system specific pathnames and enable or disable features that your system cannot support (e.g., facesaver, sound). Read the info in the dialog box and enter the appropriate file system pathnames. Click Patch to sed the exmh.MASTER script and create the main exmh file, then click TclIndex to generate the library index, and click Test to try it out. If you are satisfied, click Install to copy the main script and the supporting libraries into their destination directories.

Note: the "Script Library" and the "Install lib directory" are usually the same place. The script library is the run-time value of the library directory, while the install lib directory is the install-time value. During the Test run, the Script library is automatically set to "./lib" so you can run without installing. When you hit the Patch button, some consistency checks are done and a relative pathname will trigger a warning. You can ignore this when you are testing, but you should install a working copy that only references absolute pathnames.

NOTE: Currently you cannot leave the script library where it gets unpacked. The installation procedure really assumes that the Install Directory is a different place than ./lib. You'll get an error during the install, and in fact, background.tcl will get removed as it tries to copy it onto itself.

The original motivation for install-directory vs script-directory was AFS installations in which writable volumes have different names than their read-only, replicated volumes. In this case you want to install to the writable volume, but run from the read-only replicas.

If you get the Script library wrong, it will be manifest as a Tcl error about an undefined procedure named Exmh.

Upon startup, the install will look for ../*/.exmhinstall so you can retrieve configuration information from previous versions installed in peer directories. You can also maintain configuration information via the "Conf" button, which looks for ../*/.exmhinstall*.

A patch to the MH slocal program is included as misc/slocal.patch. The patch adds a "+" syntax to your .maildelivery file that results in messages being filed into a folder by means of the MH rcvstore library program. You can keep your patched copy of slocal distinct from the installed version because exmh runs slocal directly. The installation dialog lets you set up the pathname for your custom copy.

There is also a patch for the MH folder.c program. The patch makes folders -recurse run much faster because it avoids directories that do not have sub-folders. The patches apply to MH 6.7.

UPGRADING WITH PATCHES

There are usually patch files to go between releases (e.g. from 1.6.4 to 1.6.5). The best way to use these patches is to patch your 1.6.4 sourcedirectory and then reinstall using the procedure described above. This has the benefit of fixing the version number in the main script. Finally, this is how the patches are generated, so if you apply them to your installed directories they might not work properly.

TK SEND AND XAUTHORITY

The thing that causes the most trouble with new exmh users is the Tk send facility and the Xauthority mechanism. This matters if you use the detached background process or the exmh-async editor wrapper.

The send facility is used for communication between Tk interpreters. The most recent releases of Tk require that you have your X environment set up to use Xauthority. The details for doing this vary from X server to X server. The basic idea is that, before you start the X server you create a file, ~/.Xauthority, that contains a random bit string. The file is only readable by your user account. You pass the name of this file to the X server when you start it up. Then, each time a window is created, the client programs read this file and pass the random bit string to the server. The idea is that only programs run from your account can read the file to get the right bit string. For the details, read about the -auth or -xauth argument to your server.

Even if you get this right, you must also make sure that the old xhost security system is not used. That is, the xhost list must be empty. To do this, run the following command:

xhost -

With release 1.6.4 and later you can have exmh police your xhost list. It can clear out any hosts that creep onto the list. This typically happens with wrapper scripts used to run other programs. If you use Xauthority properly, the additional use of xhost is completely bogus and insecure. Not to mention that it breaks Tk send. Under Background Processing , select "Keep xhost list clear".

The other alternative is to recompile the Tk library with the -DTK_NO_SECURITY compile flag. This is appropriate if your X server just cannot do the Xauthority protocol, or you think your environment is safe enough. That is, you don't have to worry about other users popping up rogue windows on your display.

MORE INFORMATION

You are welcome to send bug reports and comments about exmh to the following email address: exmh-workers@redhat.com.

Exmh is available via FTP on ftp.sunlabs.com in the pub/tcl/exmh directory.

MH is available as pub/mh/mh-6.8.tar.Z from ftp.ics.uci.edu. Lately there is a new version of MH called "nmh" by Richard Coleman. You can find that at http://www.mhost.com/nmh/.

Tcl and Tk are available in the pub/tcl directory on ftp.sunlabs.com

Expect is available as pub/expect/expect.tar.Z from ftp.cme.nist.gov

Metamail (for MIME support) is available in thumper.bellcore.com:pub/nsb

Faces are available from cs.indiana.edu:/pub/faces. The individual databases are located under /pub/faces/picons/db, and they include .xbm, .xpm, and .gif representations. I recommend getting domains.tar.Z, misc.tar.Z, and unknown.tar.Z. If you have room, also get usenix.tar.Z and users.tar.Z.

Database Date Bytes Description domains.tar.Z 95.12.06 1356923 Company, Country and Univ Logos misc.tar.Z 95.11.12 58991 Things like root and postmaster news.tar.Z 95.12.06 372765 For newsgroup (not mail) unknown.tar.Z 95.11.12 19074 Default images usenix.tar.Z 95.04.13 19472394 The USENIX database users.tar.Z 95.12.08 2012905 Other personal faces weather.tar.Z 95.11.12 146329 For weather (not mail)
Glimpse is available from the University of Arizona: http://glimpse.cs.arizona.edu:1994/ or ftp://cs.arizona.edu/glimpse

To get PGP, send mail to pgp-bugs@mit.edu.

FILES

Your mail is collected under a directory usually called Mail. If you are using another mail system that uses that directory, set your Path MH profile entry to something else. The current folder and other information is stored in a file named "context" in your Mail directory. Your mail is stored as one message per file in directories that correspond to your mail folders. Nested folders are supported, up to the maximum depth supported for directories in your file system. Information about message sequences is kept in a file named .mh_sequences in each mail folder directory. The current message is in the sequence named "cur", for example. New mail is in the sequence named "unseen". You can define more sequences, up to 10 per folder.

Exmh adds a few more files for its own purposes. It uses an alternate context stored in .exmhcontext so that command line MH programs and exmh do not interfere with each other. The .folders file lists all the mail folders you have. Each folder has a .xmhcache file that has a cache of the scan output.

AUTHOR

welch@acm.org "Brent Welch"

THANKS

To Xerox PARC/CSL, for supporting this work initially, to Sun Microsystems Laboratories for continuing the support, and to all the exmh users that contributed ideas and code.
[ exmh | software | intro | faq | tutorial | reference ] exmh-2.9.0/lib/html/reference.html0000644000170700017070000012176013201227060016353 0ustar valdisvaldis Exmh 2.0 - EXMH REFERENCE (1)

EXMH REFERENCE

Contents

NAME

exmh-ref - A detailed reference to exmh functions.

EXMH REFERENCE CHAPTER

This man page gives complete, but terse, information about Exmh.

COMMAND LINE OPTIONS

There are just a handful of command line options for exmh. Note that Xt-like command line options are not supported because exmh is based on Tk, not Xt.

-bgAction action
Override background processing setting. Valid actions are: off, count, msgchk, flist, and inc.
-bgPeriod minutes
Override background period setting.
-geometry geometry
Initial geometry to use for the window. Exmh remembers the geometry when you change it interactively, so you do not really need to specify it each time on the command line.
-iconposition geometry
Initial position to use for the icon in the form +xoff+yoff. You can use minus signs instead of + to position relative to the right and bottom of the screen.
-iconic
Begin execution iconic.
-nofaces
Do not use faces database during this run.
-sedit
Override the editor command defined in Preferences and use the built-in editor (sedit) instead.
folder
It the argument is not one of the flags given above, it is assumed to be the name of a folder. In this case exmh begins in that folder.

EXMH MAIN BUTTONS

There are three sets of buttons in exmh, the main, or top row, folder operations, and message operations. The main set has global commands: Log, Help..., Bindings..., Address..., Preferences, and Quit.

Help...
Help is a menu with several choices:
This provides a useful sub-set of this man page.
This provides a highlighting key for color or monochrome screens.
This provides access to all the exmh documentation.
This displays a Frequently-Asked-Questions file. It has the same info as the help.FAQ file.
Exmh Mailing Lists...
This is a sub-menu that lets you administer your membership in the exmh-related mailing lists. See the menu entry for an explanation of the various mailing lists. The add/remove operations result in mail messages. You'll need to Send the draft messages.
A mail message is started so you can report a problem with exmh.
A mail message is started to you can register as an exmh user. There is an opportunity to sign up for the mailing lists and provide positive and negative feedback about exmh.
Get started with PGP. There is some help text and an interface to create your public key / private key pair.
Bindings...
Exmh has two sets of key bindings. One for simple editing, and another to invoke commands. The editing bindings are used in the simple editor and in the various text entry widgets. The command bindings are in effect otherwise, and they allow you to invoke various Exmh commands without using buttons or menus. This is a menu with three choices:
This brings up a dialog that lets you edit the keystroke bindings. All of the defined bindings are displayed, and you can edit their associated keystroke in place. Use the entry to the right of each command to alter or add key bindings. There are further directions in the dialog box.
These bindings result in class definitions for the Entry and Text widget classes. The default bindings are Emacs-like. See the Tk man page on the bind command for details about the syntax, if you need to. "Meta" is an OK synonym for "Mod1". To emulate Emacs, any keystroke that is defined to be <Meta-x> will also result in a binding for <Escape>x.
The compose key is used to insert 8-bit characters. This dialog shows you the key sequences used to get special characters. You can define which key maps to Compose in the Simple Edit bindings dialog.
Log
If you have enabled the debug log under the Hacking Support preferences section, then this button appears. It displays the debug log.
Address...
This is a menu with the following entries
This displays an interface to the MH alias file. You will be prompted to set up the MH profile entry that names the alias file, if needed. There are a pair of lists in the interface. To the left is a list of your aliases. Selecting one will display the address(s) of the alias in the right-hand list. Under each list are three buttons: Insert, Change, and Delete, that let you operate on the aliases or the addresses associated with an alias. As you view messages, the From address of the current message is displayed in the dialog. There is a Help button in the dialog that gives more tips about using it.
This displays a dialog that lets you customize exmh. There is also a different Help button in the Preference dialog that explains how to make selections and get more info. In particular, you can click on the descriptive label for an item to get a popup with more detailed information on the preference item.
This quits exmh. If there are pending changes to draft messages, they are saved first.

FOLDER BUTTONS

The middle set of buttons has folder commands: , , , , Search... and More...

This pops up a dialog box from which you can create new folders. When entering a folder name, the '@' character is short for the current folder name. Note that the operation is under the More... menu.
The button refreshes the color feedback of folder buttons so you can tell which folders have unseen messages in them. If you use presort inc style, then this is done automatically. However, if you read all the unseen messages in a folder from outside exmh, then it will miss the transition out of the unseen state, so the button will help reset its view of the folder state.
The button will incorporate new mail from your spool file into your mail folders. This command is also bound to the keystroke 'i'.
The button causes pending delete and move operations to occur. This command is also bound to the keystroke <Control-Return>. Know that messages marked for deletion are removed by means of the MH rmm command. In most systems, rmm will rename the message to a name beginning with either a comma (,) or pound sign (#). Unlike xmh, exmh requires that you commit changes before changing folders and doing other operations that modify the scan listing (e.g., , Sort, ). However, you can set Auto Commit under the Scan Listing preferences to have exmh automatically commit changes when needed. See also the description of the operation.
Sequences...
This is a menu of defined sequences that selected messages can be added to or removed from. If all the selected messages are already in the named sequence then clicking on an item in this menu causes the selected messages to be removed from the named sequence. Otherwise the selected messages are added to the named sequence.

By default, the only defined sequences are 'unseen' (for messages which have not yet been seen), and 'urgent'. To add to this menu, see the documentation on the sequences resources.

Search...
This is a menu of different search methods. The first two operations use a simple Find dialog. The Pick and Glimpse interfaces have their own dialogs. The menu entries under Search... are:
This help text describes the search methods in more detail.
Enter a string to find in the current message. <Return> causes the search to begin. <Control-s> and <Control-r> cause subsequent forward and reverse searches, respectively.
This search is done by scanning the folder table of contents display, so it only hits on the current folder scan output. Select the All button to select all matching messages. Use Pick for more general searching.
This provides an interface to the MH pick command. Begin by choosing from the "pick attribute" menu in the dialog. These include headers like Subject, From, To, and Cc, as well as date criteria like Before, and After. You can search for a string in the body of messages with the "Search" field. You can enter a pattern for any of these, and pick selects messages that satisfy the logical AND of these pattern specifications. Note that the Before and After patterns are date-specific, and pick understands many forms of date patterns. Read the MH man page on pick for the complete story. You can build up more complex logical search expressions by clicking the Or button.
Pick from Seq/msgs(s)
This entry lets you limit pick to a specific set of messages. In particular, you can specify a sequence name (e.g., "unseen"), and have pick find all messages with that sequence identifier. After the pick completes, a range of messages is selected that satisfies the search, and you can operate on these messages as described below.
Add to Sequence(s)
This entry lets you apply a sequence name to the set of messages that are selected by the search. You can select these later by using the "Pick from Seq" field.
Add to Sel
Set this before the pick to add the results of the pick to whatever message range is already selected in the table of contents. Otherwise a new selection is made.
New FTOC
This button causes the table of contents to be replaced with the set of currently selected messages. These can be the result of a pick, or you can just make a selection with the mouse. Warning: after projecting a new table of contents, a subsequent pick will only find things in this limited table of contents.
Mark Seen
Use this to remove the selected messages from the unseen sequence.
This brings up an interface to the Glimpse text index tool. You must first index your mail, so to get started click "index" to build your indexes. This process runs in the background, and the status of the index process is displayed in the Glimpse log. The storage overhead of the indexes is about 10% to 15%, which is quite good for a full text index system. To search, enter a word in the search area and press "Search". The button changes to a "Stop" button, although the stop may take a moment to take effect. The search results are displayed in the log. Click on the message in the log and exmh will visit that message. For more details, see the exmh-use man page.
More...
This is a menu with more folder operations in it:
Rescan forces a rescan of the folder contents. Exmh maintains a cache of the scan output that could get confused. The Rescan button forces a full scan. If you just want to scan the new messages that have arrived in the folder you are currently reading, it is more efficient to click on the folder's label in the top pane. This will invoke a scan merging procedure that attempts to preserve the cached results of previous scans. You should only need Rescan when you have reason to believe that exmh is out of sync.
This changes the table of contents to list only the selected messages. This is useful after a pick or table of contents search that has highlighted several messages throughout the folder. You must use to get the full listing back.
This will renumber messages in the current folder to eliminate any gaps in the number sequence.
Sort folder...
This is a cascade menu that provides different ways to sort your folder: , , and by the . The subject and sender sorts also do some grouping by date so that messages from one person or about one subject may be grouped into several subgroups based on their age. See the MH sortf command manual page for details.
This refreshes the display of folder buttons, and it will pick up any new folders you have created. Under MH, the command "folders -fast -recurse" can be slow. The results are saved, so you should not need to wait for this scanning unless you change your folder structure. (You can also edit the .folders file in your MH mail directory.) In nmh, this command has been patched to speed it up considerably.
This lets you delete a folder. The folder must be empty, except for .xmhcache, .mh_sequences, and any .nfs junk files.
This clears the unseen sequence from the current folder.
This runs another process in the background to update any scan caches that are out of date.
This runs another process in the background to update all the scan caches.
When MH deletes a message it really only renames it to have a name like #N or ,N if it was message N. The Purge operation will clean up these junk files that are older than 7 days. (This age parameter can be adjusted by a Preference item under the MH Tweaks section.)
This runs through all your folders deleting old junk files. This is done in the background so you can continue to use the user interface during the process.
If you use a program like Elm or Sun's Mailtool, you can import their message folder contents into the format used by MH. This menu entry brings up a dialog that lets you do this. After you specify the directory that contains the mail folders, a display with a checkbutton for each folder is created. You can select which folders to import. The originals are left alone, so you'll have to delete them yourself after you import them into MH.
This is a cascade menu entry that lets you either view the audit summary statistics or the current audit log. Note that the audit log is appended into ~/Mail/.exmhaudit when you quit exmh.
If you change something important in your MH profile, you can get exmh to reprocess it with this operation.

MESSAGE BUTTONS

The last set of commands are message operations. Several of these work in a batch fashion on all the messages in a selected set. These include Delete, Move, Link, Forward, Unmark, and Print. Some of these buttons and menu entries are disabled if there is no current message. Disabled actions have their text grayed out.

Forward the current message(s). Also keystroke 'f'.
Compose a mail message. Chose the editor to use via the dialog. Also keystroke 'c' (for "compose").
Move to the previous message. Also keystroke 'p'. Keystroke 'P' changes the current message without displaying it. Use 's' to display such a message.
Move to the next message. This will chain to the next folder with unread messages if you are at the end of the current folder. The "Next" folder is defined by the Folder-Order .mh_profile entry, and it is always the first folder in the order that has unseen messages. (This keeps you in the interesting folders and away from the dregs if you organize your Folder-Order properly.) Also keystroke 'n'. Keystroke 'N' changes the current message without displaying it. Keystroke 'F' changes to the next folder with unseen messages.
Mark the current message(s) for deletion and go to the next message. Also keystroke 'd'. If you change your mind, select the message again and it via the entry under the message More... menu.
Mark the selected message(s) to be moved to the target folder and go to the next message. Also keystroke 'm'. Note that selecting a target folder also moves the current message(s). So, you use the button if the correct target folder is already selected. If you make a mistake and want to move the message to a different folder, just select it again and right click on the proper destination folder. If you don't want to move it at all, then " the message.
Similar to move, except that the message is linked into the other folder so that it appears in both places. While this appears like a copy, the same message is shared between the folders to save disk space.
Reply...
This is a menu of reply options. By default there are two choices, but you can easily define more variations on reply. The default choices are:
Reply to the current message, only to the person that send the original. Also keystroke 'r'.
Reply to the current message, including on the cc line everyone that got the original message. (It invokes MH repl with: -cc cc -cc to). Also keystroke 'R'.
This pops up a display that tells you how to program new reply buttons. You'll need to be familiar with the MH repl command and its filters. Check out the repl and mh-format manual pages.
More...
This is a menu of more message operations.
Print the current message, or the selected set of messages. The print command is defined via the dialog. The whole message is printed, headers and all.
Cancel a move or delete mark on the selected message(s). Also keystroke 'u'.
Display a new toplevel window containing the current message.
Display the first unseen message, if any. Also keystroke 'U'.
Use the MH burst command to split up a digest message into its individual messages. In addition, the new messages are added to the unseen sequence. You can control whether or not the original message is replaced with just the digest header by specifying burst options in your .mh_profile. (E.g., burst: -inplace).
This simply copies the current message(s) to a file selected via the file selector dialog.
This copies the current message into the drafts folder and opens your editor on the message.
This opens your editor on the message so that you can annotate it.
This simple runs uudecode with the current message as input. A file selection dialog lets you choose the name of the resulting file.
This is useful for non-MIME messages that contain a postscript file. The message body (everything from the initial %!PS onwards) is put into a temp file and then the Postscript Print Command is used to print that file.
This runs a UNIX command over the current message (all of it). A dialog lets you set the command, with occurrences of $file replaced with the pathname of the message. The default value of the UNIX command is hiding under the Print entry.
This runs a UNIX command over a temporary file containing the body of the current message.
This puts the current message(s) back into the unseen sequence.
Replace the current message with an encrypted version of it.
old PGP...
This is a menu of operations that apply to PGP messages that are not wrapped up in a MIME format. Those are handled automatically. This menu is used to tell exmh explicitly what to do. You can , , or .
Scan through the message body and look for URL and URN references. If any are found, they are highlighted and made into active text. Click on the text and your web browser will be started on that URI. You can set the command to use via the URI section. Also keystroke 'z'.
If you have manually selected an embedded URL, then use this menu entry to get exmh to ask your web browser to display the selected URL. If the automatic scanning doesn't work perfectly, you can do a manual selection on top of an incorrect active text button. NOTE: This also works if the URL was selected outside of exmh!!
If you get a message in parts, as a MIME type message/partial, then select all the messages that have the parts and invoke this operation.
Choose a folder for the current message based on the from address.
Post a copy of the current message to a newsgroup. You'll be prompted for what group.

SEDIT

The built-in editor, sedit, has a dozen or so commonly used editing operations bound to keystrokes. These are Emacs-like, but you can change them from within the editor through the "Simple Edit" dialog available under the main "Bindings" menu. In addition, the editor has a number of buttons and menu entries used to manipulate your draft messages.
Abort
This deletes the draft message and removes the editor window.
Save&Quit
This will save the message and quit the editor window. The idea is that you will come back to the draft via the drafts folder later.
Crypt...
This is a menu of options that use the Pretty Good Privacy package to to encryption and authentication. An explanation of pgp is beyond the scope of this manual.

The options in the menu determine how your message will be encrypted or signed when the message is sent.

These values default to the values provided on the PGP page and are reset for every new message.

There are currently three formats supported for signed or encrypted messages:

Plain
This uses no encapsulation whatsoever for the signed message. This format is compatible with older non-MIME compliant mail programs.
Application/PGP
This uses the now deprecated Application/PGP MIME type. This type was deprecated because it turned out to be insufficiently flexible.
Multipart/MIME
This uses Multipart/signed MIME type with the signature part encoded as an application/pgp-signature. This is compatible with other non-PGP digital signature schemes. Many minimally compliant mail programs see your signature as an attachment.

There are also four signature operations supported via the Sign sub-menu:

None
No signature is produced.
Standard
This causes the message to be digitally signed so that the recipient can determine that you were really the author.
Clear Sign
This causes a signed, but not encrypted message to be passed in clear text so even if a recipient doesn't have PGP available, they can still read the text.
plus Encrypt
This causes the message to be encrypted as well as signed.

Toggling "Encrypt Only" causes the message to be encrypted so that only the intended recipient can read it. If you have enabled caching of passphrases you can use "Clear Passphrases(s)" to clear the cache. Users with multiple private keys may select which key to use for signatures via "Choose Key" (or the SEDIT area described in the next paragraph).

If PGP is enabled, and "sedit PGP password" is selected in the , a field for entering a PGP password appears at the bottom of the SEDIT window. If your password is provided in this field, then the values set in the Crypt... menu are invoked. If no password is provided, then encryption is not used AND the message is not sent. This makes it harder to send un-encrypted messages out by mistake.

If PGP is enabled and "sedit PGP password is not selected in the , a popup window appears after pressing the SEND button.

Help
This button brings up a window with a short explanation of the editor.
Quote...
This is only active while you are replying to a message. When you are replying to a message, the file named "@" is a symbolic link to the message to which you are replying. When this file is inserted, it is formatted a bit, unlike the Insert File... operation. The mail headers are stripped off, quoted-printable text is decoded so you get 8-bit characters in the edit buffer, and each line is prefixed with a short string to distinguish the inserted lines. You can set this prefix via an Xresource, replPrefix. The default prefix is "> ". If you want to change this and still have trailing blanks, it turns out this works OK. The resource value seems to begin with the first non-blank character, but then extends all the way to the newline character.
Sign
This appends your ~/.signature file to the draft. If this file is instead an executable script or program, it is executed in order to generate the signature.
Sign...
If you have multiple files that match the ~/.signature* pattern, the Sign button is replaced with a menu of possibilities. If you choose the autoSign Simple Editor Preference, then this menu is used to choose which signature file (or program) is used when automatically signing the message as it gets posted.
Send
When you are done with the message, click Send. This is also bound to the keystroke <Control-c><Control-c>.
Text...
This menu is used to add bold, italic, underline, etc. to your messages. This results in a MIME message of type text/enriched. The formatting commands are supposed to be palatable to a non-MIME reader, but you may want to take this into consideration. If you disable the "Format mail" setting (described below), the looks are discarded before sending the message.
More...
This menu contains a few entries for less common operations. They are:
Keep on send
This is a checkbox menu item that is off (un-highlighted) by default. If selected it prevents the editor window from disappearing after you send or abort a message. This is useful if you'd like to compose a few similar messages. (I also use it to debug the enriched text formatter.)
Format mail
This is a sub-menu of formatting options. The first three options are mutually exclusive and determine when and how the text in your message is formatted to fit into standard length lines. The choices are:
No Line Breaking
Don't do any formatting at anytime.
Line Break at Send
Post process the message after you hit the send button to break long lines.
Line Break when Typing.
At each keystroke check to see if the current line is too long, wrapping it if necessary. If you use this then you should know about the "format" command that reformats a paragraph. By default, that is bound to <Meta-q>
Attempt mhbuild
If this is selected, your message is run through mhbuild in order to expand any # directives that format a MIME message. See also the "Run mhbuild now" menu entry below, and see the mhbuild man page for details.
Quote Printable
If this is selected, then any text MIME parts are run through the quoted-printable encoder to wrap up 8-bit characters in a 7-bit safe encoding. The Quoted Printable default preference setting under Simple Editor can be set to automatic, never, or always. In automatic mode, quoting is enabled when you enter a Compose key sequence to generate an 8-bit character.
Run mhbuild now.
This processes the message assuming you have mhbuild directives, and then lets you edit the result.
Cite Selection
This formats and inserts the current selection. It is assumed to be in the currently displayed mail message, and the sender of that message is identified before the formatted text. Hint: this is the only useful way to include text from PGP encrypted messages and text/enriched messages. The formatting of text/enriched is lost, however.
Attachment
This is a menu of attachment options.
Attach File...
This brings up a dialog box that lets you attach a file using MIME. It tries to determine the type of the file based on nametemplate entries in the metamail mailcap description file. It presents a dialog that lets you override the type, add a Content-Description, and choose an encoding for the file. When you attach the first Part of a message you are asked whether or not to save the existing message body. If you save it, it becomes the text/plain first part of the multipart message.
Insert File...
This simply inserts a file at the current insert point.
Attach Reference...
This sets up an Message/External-Body MIME message part. This is useful for sending around pointers to files available via FTP or on your local file system.
Attach PGP Keys...
Insert your PGP keys into the mail message. You can use the key selector to choose any key in your public keyring. Just type in a pattern that matches part of the key ID. Matching keys are displayed in the listbox.
Whom
This entry displays a small window with the network addresses of the recipients of the message. Clicking the button a second time makes the window go away.
Spell...
This runs either the UNIX spell or ispell command. Choose between these two options in the Simple Editor . (Don't confuse that with the setting under Editor Support .) If you use ispell then the draft is reloaded after ispell terminates. If you use spell then the output of spell is put into a second pane inside the editor window. That's all - nothing fancy.
Find SEL
This searches the draft for the current X selection. The intent is that you select misspelled words in the output of the spell command and use this menu entry to locate them in the draft. (The find and keybinding mechanisms were stressed by this addition - expect a cleanup someday. There is no reasonable way to define keystroke accelerators for the find and still be able to change them in the Bind dialog. -don't ask...).
Save Buffer
This saves the editor buffer into a file in your drafts folder. Most likely you really want the "Keep on Send" function instead of Save, because that function preserves the draft after you send it, while ordinarily (in spite of "Save") MH will rename the draft after you send it.
Mime Preview
This displays the message as it will appear when an exmh user receives it. A detached top-level window is used, as with message Clip.
Alternate Editor
Save the draft and invoke your alternate editor on the message. Define the alternate under the Editor Support .

AUTHOR

welch@acm.org "Brent Welch"

THANKS

To Xerox PARC/CSL, for supporting this work initially, to Sun Microsystems Laboratories for continuing the support, and to all the exmh users that contributed ideas and code.
[ exmh | software | intro | faq | tutorial | guide ] exmh-2.9.0/lib/html/blu-ball.gif0000644000170700017070000000047213201227060015704 0ustar valdisvaldisGIF89a ¥ZÞ„KJœµ41ŒcÿŒ§ÿÎ{Æ­Ö{{Æ„ÿlcÎÖ(!ÿÎsÿïœkÆJs14ÿÿÿÿ ½çJecΔ½Z¥ÆÿGBÎÿÿ!ù, WÀNGaJ$L aÂ@¡– ¤Ó˜ NœÇ'si˜PD©Â‰‰Ãƒ#‰Œ.@"ð LpÀ4yp$  "" ! ”J ŽA;exmh-2.9.0/lib/html/exmh-fans.html0000644000170700017070000001224713201227060016302 0ustar valdisvaldis User's Comments About exmh

User's Comments About exmh

  • josh@cayman.com I like exmh because... it so damn nice! And the mime support is great. Perhaps the most impressive and useful free X applications I seen. XV is a close second.
  • cwg@mcc.com I like exmh because...it does more than any other mail program.
  • marc@destek.net It is the most complete E-Mail GUI for X11 that I have encountered. The MIME support is great. User extensibility (such as providing for embedded URI references) is a great feature.
  • frederic@parc.xerox.com It provides a friendly X user interface to multiple mail folders, including automatic filing capabilities.
  • hdavis@parc.xerox.com
    • It sorts mail into folders as they come in
    • Folders are hierarchical
    • It has a good user interface
    • It is well supported -- and with good cheer!
    • The defaults, user interface, and support made it trivial to start using
    • It incorporates an easy call to ispell
    • It incorporates sender face bitmaps :-)
  • rucklidg@parc.xerox.com It makes it possible to handle lots of messages, especially refiling them - my inbox used to build up to thousands of messages because refiling was a pain (more commands to type); now, a quick right-click... the recently-used folder list is very useful for this: I have a folder for each of the people I correspond with, so there are enough that I don't want to see them all on the screen at once, but the cached list (with two lines) hits often enough that it's not a problem to deiconify the main folder list window for the few that miss. I like the LRU scheme for replacement.
  • rasmusse@parc.xerox.com I find it more convenient and easier to use than any other mailing system I've used previously - not that I've used a lot...
  • jph@solo.com
    • it's mh based,
    • it's fully functional,
    • it's customizable, extensible, and free,
    • it's well conceived, tasteful, and well supported.
  • goggi@zafir.dc.luth.se I like exmh because it's the best. I haven't seen any tool other than real expensive ones that let me cope with several hundreds mail per day with this ease. Not only is it efficient and easy to use, it's powerful and high-tech! Just one example: for the first time I can really make use of my 2048-bit pgp-key! (:
  • I don't really like the richness of configurations and possibilities in exmh. It's far too well-equipped and richly designed (-: Nah, I can't find anything to complain about with Exmh, I really can't. Often when I find out about something to that might be a problem it's when the workaround or a patch is posted to exmh-users. So generally I just think it's a great mail-handler!
  • pryan@rp.csiro.au I like exmh because...
    • It's not DEC's painful dxmail.
    • I can see the source for it.
    • It's widely used.
    • It's readily extensible.
    • There's a wide and vocal community of people discussing bug fixes and common mistakes.
  • Ng.Fo@hk.super.net I like exmh because it's really cool, and even better than zmail. Can help me deal with lot's of email messages per day, say 500.
  • daves@cc.bellcore.com I like exmh because...
    • Good installation process
    • Scan caching is nice - gives exmh good performance characteristics
    • Background processing capability
    • Message facility. You should play this up more. It was real easy to put a shell in my .maildelivery file that causes exmh to de-iconify and change folder to, say my boss's folder, when my manager sends e-mail.
  • cedric.scott@sse.ie It saves me about one hour per day. I started using exmh earlier this year. We now have about a dozen users.
  • allen@ibmoto.com It does things that other mailers do not do. The support and new features from the author are excellent. Just when I find a new things that can be done with mail, you implement it for the next release.
  • chris@wg.estec.esa.nl It supports mime messages, multiple mail drops, user tweaks, but probably most of all because it is being actively improved. After a very short learning period it became my first choice mail reader. Other people here who I've shown it too have had the same reaction.
  • citrit@rpi.edu Overall I find exmh to be a very good product and I am always telling people about it. We have ZMail as the default GUI based mail handler, when people start complaining how slow it is and how much it crashes I tell them I have a fix :-). I convert their zmail folders into mh folders and away we go. Thanks for all your work, exmh is a wonderful package.
  • jonesn@hursley.ibm.com
    • It is based on standard MH, so I can still use the good old MH commands over a SL/IP link
    • It supports MIME well
    • Performance is pretty reasonable
    • It's simple the best mailer around I've seen (for SMTP mail). I keep telling my friends about it. Thoroughly recommended. You've done a brilliant job
    • I've really struggled to find anything bad - there isn't really!
exmh-2.9.0/lib/html/software.html.old0000644000170700017070000001461613201227060017025 0ustar valdisvaldis exmh- Related Software

Related Software

In the true spirit of UNIX, exmh builds on many other small tools. Here are most of them:

[Req]indicates that exmh requires this package to run
[Sug]indicates that this package is required for some functionality
[Opt]indicates that this package is optional

[Req]exmh-2.8.0.tar.gz
The latest version of exmh. This requires Tcl/Tk 8.0 or higher. You might as well have the latest (non-beta) version of Tcl/Tk.
[Sug]SourceForge CVS.
The source code repository for exmh is at SourceForge.
[Req]nmh
A cleanup of the MH code that works with exmh and is much easier to compile and install on your UNIX systems.
[Opt]rand-mh
The original MH mail package. This is also the web site for the MH and nmh book
[Req]tcl8.4.9-src.tar.gz
"Tool Command Language" What is TCL?
[Req]tk8.4.9-src.tar.gz
[Req]mm2.7.tar.Z
Metamail, used to display and process MIME messages. exmh requires this package to display MIME messages, but you may use mhbuild to compose MIME messages.
[Sug]Faces/Picons
With the Picons package (a.k.a. Faces), the faces of your correspondents can be displayed alongside their messages, and you may compose a "face" header of your own.
[Sug]Glimpse
The Glimpse is a full text index system with low space overhead. Exmh provides an interface to its search engine that makes it easy to find mail messages in any of your multitude of folders.
[Sug] netscape-remote.
A Tcl extension that provides efficient interaction with netscape. Look for this in the misc subdirectory of the exmh distribution.
[Sug]Procmail
The procmail facility is a general mail handler that can sort mail into folders as it arrives. Exmh can work with any mail filtering program. This is different than the filtering mechanism built into MH. Here are some other mirror sites: Ohio State, PSG, UC Santa Barbara, Germany.
[Sug]uudeview
This is a viewer for binhex, base64, uuencode and xxencode files.
[Sug]ifile intelligent mail filter
Intelligent message refiling. This uses a text-based learning algorithm to learn user preferences for which messages should go in which folders. Here is the latest README.
[Sug]Img
A package that adds additional image types to the Tk photo widget, allowing automatic in-line display of additional image/* MIME types. Please see the Tkimg SourceForgeProject for the latest software release.
[Sug]Par
A very sophisticated quoting engine. The cite.pl script uses this. Find cite.pl in the misc/ directory of the exmh distribution.
[Sug]Mimep
A printing package for MIME messages.
[Sug]openldap
Commands for accesing LDAP servers.
[Sug]Antiword
A tool that is used for inline display of MsWord documents.
[Sug]SpamAssassin
A popular spam-filtering package. Exmh is able to invoke the "sa-learn" program to train the Bayesian classifier used by SpamAssassin, so it produces better results.
[Sug]Laola
Another tool that can be used for inline display of MSWord documents. The Antiword package is however known to produce "better" results.
Back to the exmh index exmh-2.9.0/lib/html/software.html0000644000170700017070000001465213370476526016274 0ustar valdisvaldis exmh- Related Software

Related Software

In the true spirit of UNIX, exmh builds on many other small tools. Here are most of them:

[Req]indicates that exmh requires this package to run
[Sug]indicates that this package is required for some functionality
[Opt]indicates that this package is optional

[Req]exmh-2.9.0.tar.gz
The latest version of exmh. This requires Tcl/Tk 8.0 or higher. You might as well have the latest (non-beta) version of Tcl/Tk.
[Sug]SourceForge CVS.
The source code repository for exmh is at SourceForge.
[Req]nmh
A cleanup of the MH code that works with exmh and is much easier to compile and install on your UNIX systems.
[Opt]rand-mh
The original MH mail package. This is also the web site for the MH and nmh book
[Req]tcl8.4.9-src.tar.gz
"Tool Command Language" What is TCL?
[Req]tk8.4.9-src.tar.gz
[Req]mm2.7.tar.Z
Metamail, used to display and process MIME messages. exmh requires this package to display MIME messages, but you may use mhbuild to compose MIME messages.
[Sug]Faces/Picons
With the Picons package (a.k.a. Faces), the faces of your correspondents can be displayed alongside their messages, and you may compose a "face" header of your own.
[Sug]Glimpse
The Glimpse is a full text index system with low space overhead. Exmh provides an interface to its search engine that makes it easy to find mail messages in any of your multitude of folders.
[Sug] netscape-remote.
A Tcl extension that provides efficient interaction with netscape. Look for this in the misc subdirectory of the exmh distribution.
[Sug]Procmail
The procmail facility is a general mail handler that can sort mail into folders as it arrives. Exmh can work with any mail filtering program. This is different than the filtering mechanism built into MH. Here are some other mirror sites: Ohio State, PSG, UC Santa Barbara, Germany.
[Sug]uudeview
This is a viewer for binhex, base64, uuencode and xxencode files.
[Sug]ifile intelligent mail filter
Intelligent message refiling. This uses a text-based learning algorithm to learn user preferences for which messages should go in which folders. Here is the latest README.
[Sug]Img
A package that adds additional image types to the Tk photo widget, allowing automatic in-line display of additional image/* MIME types. Please see the Tkimg SourceForgeProject for the latest software release.
[Sug]Par
A very sophisticated quoting engine. The cite.pl script uses this. Find cite.pl in the misc/ directory of the exmh distribution.
[Sug]Mimep
A printing package for MIME messages.
[Sug]openldap
Commands for accesing LDAP servers.
[Sug]Antiword
A tool that is used for inline display of MsWord documents.
[Sug]SpamAssassin
A popular spam-filtering package. Exmh is able to invoke the "sa-learn" program to train the Bayesian classifier used by SpamAssassin, so it produces better results.
[Sug]Laola
Another tool that can be used for inline display of MSWord documents. The Antiword package is however known to produce "better" results.
Back to the exmh index exmh-2.9.0/lib/html/AliasAddr.html0000644000170700017070000000124313201227060016232 0ustar valdisvaldis Aliases and Addresses Help

Aliases and Addresses Help

Exmh supports two different address books, you can use either or both. They are independent of each other. The two address books are:

MH Aliases, as the name implies, are a capability of the MH foundation upon which exmh is built and can be used with other MH tools. The exmh Address Database is supported solely within exmh.

Main Help Index

exmh-2.9.0/lib/html/Reply.html0000644000170700017070000000340113201227060015477 0ustar valdisvaldis Reply Menu Setup

Customizing the Reply Menu

In general, you can define buttons and menus for exmh by means of X resource specifications in your ~/.exmh/exmh-defaults file. Put these resources at the beginning, before any comment lines about the stuff below being automatically inserted.

If you want a reply button, try this.

*Mops.ubuttonlist: repl
*Mops.repl.text: Repl
*Mops.repl.command: Msg_Reply (your favorite repl arguments here)

Note that "repl" was used. The button name "reply" is already taken by the Reply... menu button. You can also add new entries to the reply menu. Try this:

*Mops.reply.m.uentrylist: sep ack
*Mops.reply.m.l_ack: Acknowledge
*Mops.reply.m.c_ack: Msg_Reply -cc me -nocc cc -filter /usr/welch/Mail/mhl.ack

The "uentrylist" resource lists the menu entries defined added by you. It is meant to be redefined by you. It's default value is:
*Mops.reply.m.uentrylist: sep help

So, the "help" entry that calls Msg_ReplyHelp will disappear once you start defining your own reply variations, unless you add "help" to your uentrylist resource.

"sep" is a special menu entry type defined in app-defaults to just be a menu separator - a thin line.

"ack" is the your name for the menu entry, and "l_ack" defines the label on the menu entry. "c_ack" defines the Tcl command associated with that entry. Msg_Reply takes the same arguments that the MH repl command does. You'll have to check out the repl man page for all the details."

More details about custom buttons and menus.

Main Help Index

exmh-2.9.0/lib/html/symlink.html0000644000170700017070000000307713201227060016103 0ustar valdisvaldisExmh symlink attack

Exmh symlink attack

Jan 10, 2001: Exmh made the security news via report to BUGTRAQ about the following:
A problem in the bug reporting system for exmh, an X-based interface for the MH mail, can cause overwriting of arbitrary system files that are writable by the user running exmh. When exmh encounters a problem in its code, it opens a dialog that asks the user what happened and then allows them to send a bug report to the author. If the user chooses to e-mail the bug report, exmh creates the file /tmp/exmhErrorMsg. If the file is a symlink, it will follow the symlink, overwriting the file that it is linked to.

This vulnerability applies to all versions of exmh 2.2 and earlier. However, users of these versions can set the TMPDIR or EXMHTMPDIR environment variables to change the /tmp choice. This feature already exists and you do not need to apply the patch to enable it. Any exmh user can avoid the attack by setting either of these environment variables to a directory they own.

The default of /tmp has been changed with a fix to the env.tcl file that decides which directory to use for temporary files. Instead of using /tmp as the default, the program now uses /tmp/username and ensures that the directory is owned and write-only to the user.

This fix is in exmh-2.3.

Users can apply the patch to their env.tcl, or simply install a new version of that file.

exmh-2.9.0/lib/html/whatis.html0000644000170700017070000000661513201227060015715 0ustar valdisvaldis Exmh

What is exmh?

An Introduction by the author, Brent Welch , welch@acm.org

Exmh is an X user interface for MH mail. MH provides a set of UNIX commands that manage folders and mail messages. MH has a zillion features as a result of several years of availability. Exmh provides a graphical interface to many of these features, but not everything. You can do all the ordinary things like viewing the messages in a folder, and reading, deleting, and refiling messages. In addition, the interface handles arbitrary nesting of your folder hierarchy.

What exmh supports well is sorting arriving mail into different folders before you even read them. You can sort with the MH .maildelivery filtering mechanism, procmail, or any system that adds new messages to the unseen sequence of a folder. exmh provides an easy way to find newly arrived messages after they have been squirreled away. It highlights what folders have new mail, and within a folder it indicates which messages have not yet been read.

MIME format messages are parsed and displayed. MIME is a multi-media mail standard that allows transmission of images, audio, enriched text, FTP pointers, etc. via email. While there is some support for composing MIME messages in the current version, the composition facilities need a little more work.

You can use your favorite editor to compose mail messages, or you can use a simple built-in editor that provides some Emacs-like keybindings. With the built-in editor you can compose text/enriched (bold, italic, underline, etc.), and you can create multipart messages by inserting files of various MIME types.

Exmh is written in TCL/TK . The implementation is open and flexible. There are several levels of customization:

  • Each module of the implementation exports a few knobs and dials in a preference interface. There about 20 modules, so there are altogether way to many knobs at this point. But, hey, the table-driven implementation makes it easy to export settings.
  • The button and menu structure is defined via X resources, You can easily add more buttons or menus to invoke new functionality that you add to exmh.
  • TK widget attributes such as colors, fonts, and cursors, are controlled by X resources. You add make site-wide or personal resource definitions to tune the appearance of exmh.
  • Exmh supports a personal library of Tcl extensions. You can provide new functionality and add a button for it. In addition you can override parts of the implementation. This area could be stronger with the addition of more hook points so you do not have to override a whole module, but this will improve over time.

THANKS

To Sun Microsystems Laboratories and my manager, John Ousterhout, for supporting my current exmh work, and to the Computer Science Lab at Xerox PARC, which supported the initial development of exmh.

Many thanks to Scott Hutton who took my feeble attempt at an exmh home page, plus my on-line manuals, and produced a nice set of web pages.

Back to the exmh index exmh-2.9.0/lib/html/Lists.html0000644000170700017070000000233713201227060015511 0ustar valdisvaldis Mailing Lists

Mailing Lists

There are three exmh-related mailing lists:

exmh-announce@redhat.com
This is a moderated list that is used for announcements about new exmh releases. This gets very little traffic.
exmh-users@redhat.com
This is an open list used for general question and answer about exmh. This list also gets any messages sent to exmh-announce, so you'll hear about new releases on this list, too. There is also a digest version of this list.
exmh-workers@redhat.com
This is an open list meant more for experts that are dabbling with the internals of exmh. This list is no longer shared with exmh-users. You may wish to subscribe to both.

Use the menu operations under Help... Mailing Lists to add or remove yourself from these lists. If you need more detailed help about administration of these lists, send mail to exmh-users-request@redhat.com with a message that just says "help"

Main Help Index

exmh-2.9.0/lib/html/Bindings.html0000644000170700017070000000255213201227060016147 0ustar valdisvaldis Binding Help

Binding Dialog

Use the binding dialog to change the keybindings for command accelerators. A binding ties an event to a Tcl command.

Event Syntax

  • Any sequence like <Meta-x> also results in a binding for <Escape><x>
  • Case is significant in the keywords Control, Meta, Shift, Key, BackSpace, etc.
  • Multiple keystrokes can be bound to the same command. Separate them with a space, e.g.: <BackSpace> <Prior>

Changing a Binding

  • Edit the keystrokes for the existing commands in each entry widget.
  • Press <Return> in the entry and the change takes effect right away. Or, click the Save button, which makes the dialog go away, too.

Defining a New Accelerator

The Define button and the entries at the top are used for new commands. For example, to make <Control-z> close the window, enter
Command: wm iconify .
Key: <Control-z>
and then press the Define button.

Deleting a Binding

Delete bindings by clearing the associated entry and pressing Return.

Your settings are saved in ~/.exmh/exmhbindings

Main Help Index

exmh-2.9.0/lib/html/Keys.html0000644000170700017070000000617613201227060015333 0ustar valdisvaldis Keyboard Shortcuts

Keyboard Shortcuts

Several of the folder and message operations have keystroke bindings so you can do much of your browsing with hands on the keyboard. You can browse and edit these bindings with the Commands entry under the Bindings... menu. The default bindings include:

Folder Operations

<Control-return>- Commit pending changes.
<Key-i> - Incorporate new mail into folders.
<Control-n> - page down folder table of contents.
<Control-p> - page up folder table of contents.

Sending Mail

<Key-f> - Forward current message or messages.
<Key-r> - Reply to sender of current message.
<Key-R> - Reply to sender and all recipients of the message.
<Key-c> -
Compose a new mail message.

Moving Among Messages

<Key-space> - Page down or select and display next message.
<Key-BackSpace> - Page up.
<Key-n> - Select next message and display it.
<Key-N> - Select next message, but do not show it.
<Key-p> - Select previous unmarked message
<Key-minus> - Select previous message, whether or not it is marked
<Key-P> - Select previous message, but do not display it.
<Key-dollar> - Select last message, but do not display it.
<Key-asciicircum> - (tilde ~) Select first message, but do not display it.
<Key-s> - Show current message.
<Key-U> - Select first unseen message in the folder.
<Key-F> - Change to next folder with unseen messages.

Deleting and Refiling

<Key-d> - Delete current message and advance to next message.
<Key-D> - Delete current message and select next message, but do not show it.
<Key-m> - Move current message and advance to next message.
<Key-M> - Move current message, advance to next message, but do not show it.
<Key-u> - Unmark. Undo a pending Delete or Refile.
<Key-period> - Automatically refile the current message.

Miscellaneous

<Key-A> - Interpret selection as a Sun Calendar Manager appointment.
<Key-g> - View selected URL in a browser window.
<Key-z> - Scan current message for URLs. They turn into buttons you can click to view the URL.

<Control-s> - Find next occurrence.
<Control-r> - Find previous occurrence.
<Key-question> - Display command binding dialog.

Keyboard Folder Selection

<Key-plus>- Enter folder selection mode. Each + toggles between Target and Change folder.

<space> does folder-name completion.
<Control-c> cancels folder name selection operation.
<Return> accepts folder name selection.

Main Help Index | Quick Intro

exmh-2.9.0/lib/html/yel-ball.gif0000644000170700017070000000047213201227060015713 0ustar valdisvaldisGIF89a ¥½½ÎÎcÎη½ÿêŒ÷ÿûÿçïÌÎBÆÆ{ÚÞÿÿWZÿü1ÃÆ^c„„ssãçÂÆ{”ûÿ!ÖÖEJ§­qsÿÿÿÿÿÉÎcZY‚„kk—œ‰Œ1ÿ䥯µœœJÏÖJJÇÎûÿ!ù, W@f‚¡†cÙl G“8m ”ÄJ 6(‚¨`P<ªQ)@†@!QœFð 0p&  &$ &”!J  ŽA;exmh-2.9.0/lib/html/DSN-MDN.html0000644000170700017070000000776113201227060015461 0ustar valdisvaldis Delivery Status Notifications, Message Delivery Notifications, and you...

Delivery Status Notifications

Basically, Delivery Status Notifications (DSNs) define a special MIME type to report message status information. The types of information that are transmitted are successful delivery, delayed delivery, or failure, with possibly additional diagnostic information. A DSN is not able to report if a user has actually looked at a message, or any other status beyond "it was placed in their mailbox".

Message Delivery Notifications

Message Delivery Notifications (MDNs) build on the DSN framework to report the final disposition (seen, discarded, etc) once it has been placed in a user's mailbox. There are some caveats here:

  • Receipt of a "read" MDN does not imply that the message was understood or dealt with - merely that it was displayed for the user to read. The user may have been asleep, on the phone, or just didn't want to act on your mail.
  • Not all mail programs support MDNs. If the recipient's software doesn't support it, you won't get one back.
  • Even if the mail program supports MDNs, the site or user may have disabled them for administrative or policy reasons. Similarly, there is no guarantee that a DSN will be returned if requested.

EXMH Support

EXMH is able to display both DSNs and MDNs without further configuration. Some additional configuration is required to make full use of the support.

DSN options are located on the 'Preferences - Simple Editor' panel, and are also settable on a per-message basis via the 'DSN...' menu in Sedit. Note that for DSN support to work, you must have a version of MH that supports it (which may require some patching. A patch for nmh 1.0.4 is available in the Exmh distribution in misc/README.dsn-nmh

The EXMH MDN support is able to display a MDN without further configuration. However, to ask for a MDN on a given message, you need to select 'Ask for Receipt' in the Sedit 'More...' menu. In addition, you must put the address to send the MDN to in the 'Preferences - MIME' panel, in the 'Disposition Notification To:' field. This should probably be set to the same address as your From: field, unless you've read RFC2298 and fully understand the implications.

The 'Send MDNs' button in the 'Preferences - MIME' panel controls when to send an MDN. By default, MDNs are not sent. A reasonable value is 'Auto/Ask', which will automatically send an MDN unless a condition is detected prompting a check with the user (such as an MDN directed to a mailing list, or not back to the message sender, etc).

The nitty gritty technical stuff

DSNs and MDNs are defined in the following IETF RFCs:


Valdis Kletnieks
Modified: 07-Aug-2004 exmh-2.9.0/lib/html/exmh-faq.html0000644000170700017070000011072013201227060016115 0ustar valdisvaldis exmh FAQ

exmh Frequently Asked Questions

[ exmh | software | intro | tutorial | guide | reference ]
1
How do I configure exmh to use a POP mail server?
1b
Does exmh speak IMAP (NO)
2
I'm having problems with non-US ASCII characters
2a
How do I display ISO-8859 fonts so that my special characters show up?
2b
How do I insert special 8-bit characters (latin-1)
2c
How do I get RFC-2047 encoded headers such as the "From:" address of messages to display correctly in the folder TOC?
3
I can't get background incorporate to work. What am I doing wrong?
4
I'm having problems with X authorization
4a
How do I get Tk send to work?
4b
How do I start my X server so it does Xauthority right?
4c
How do I just disable the xauth stuff in exmh?
4d
rsh commands don't work between home and work, because the accounts are different on the two machines.
5
Where do I find Faces and Metamail packages?
6
How do you get an X-Face: line into your outgoing mail messages?
6b
How do you display an X-Face: header line?
7
Can I use EXMH as a news reader?
8
How do I change those default wheat-colors for the widgets in EXMH?
9
What's the difference between presort and multidrop inc-styles?
10
How do I fix the "exmh-bg lost UI {process XXXX}" message?
10b
What does "exmh-bg cannot rendez-vous with UI - exiting" mean?
11
How come messages are not really removed when I delete them?
12
Why doesn't the flag go up when there is new mail in the spool file?
13
Why isn't there a Reply button, but only a reply menu?
14
Are there newsgroups or mailing lists for discussion of exmh?
15
How do I set up the templates for mail messages?
15a
Can I have templates associated with folders?
16
How do I get a copy of mail I sent saved into a folder (easily).
17
What is a good alternate Print command to get good formatting?
18
How do I change the folder table of contents listing?
18a
Remove the leading words of the message
18b
Handle message numbers > 999
18c
Add annotations to messages that have been replied to.
18d
Colorize message headers.
19
How do signatures work?
20
How do I set up sendmail and my PPP dial-up account?
21
How do I make exmh look good with WindowMaker or GNUstep?
22
How do I make exmh want to display messages as plain-text rather than HTML-formatted?
23
How can I stop my own address from appearing on the cc list when I reply to messages?
24
How do I fix errors from the scan program?

1. How do I configure exmh to use a POP mail server?

First you must make sure that your MH (or nmh) is compiled with support for POP. You can check by running "inc -help" and check that it supports the -host command line argument. You set the name of the POP3 mail server host under Incorporate Mail or The Top Ten preferences. You can also set up a ~/.netrc file that lists your POP3 servers and user accounts. This option requires the Expect program so that exmh can automatically manage your POP3 password.

I don't have Expect; can I still use a POP mail server?

If you do not have expect, you must put your password into your .netrc file and leave your POP3 mail host preferences setting empty. The .netrc file contains lines in the following format:
machine mail.wherever.com login yourlogin password "a secret"

1b. Can I use an IMAP server?

Exmh does not directly support IMAP. However, you can use mail clients like fetchmail to get your mail from an IMAP server. That gets the mail onto your local machine, and then exmh/MH can read it from there.

2. I'm having problems with with non-US ASCII characters

2a. How do I display ISO-8859 fonts so that my special characters show up?

Put an Xresource specification into your ~/.exmh/exmh-defaults file:

*Text*font: -*-courier-*-*-*-*-*-*-*-*-*-*-iso8859-* 
*Ftoc*Text*font: -*-courier-*-*-*-*-10-*-*-*-*-*-iso8859-*

2b. How do I insert special (8-bit) characters?

There are many Compose key sequences that are defined to let you do this. Your X environment may also specially map some keys. For a list of the Compose key sequences, select the Compose Key menu entry under Bindings. Press the Compose key and then the two characters in the left list in order to get the special character on the right hand side. You can redefine what the Compose key is mapped to in the Simple Edit Bindings... dialog.

2c. How do I get RFC-2047 encoded headers such as the "From:" address of messages to display correctly in the folder TOC?

The folder table of contents is generated by the MH/nmh scan program. Only the nmh scan program supports decoding RFC-2047 headers. The nmh package is highly preferred over the older MH due to security holes in MH.

NOTE: This answer depends on your UNIX system having a complete and correct implementation of "locales".

You have to do several things right for everything to work:


  1. Use decode in the appropriate places of relevant format or filter files. Here's an example scan.form (this is the nmh default scan.form):
    %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\
    %02(mon{date})/%02(mday{date})%<{date} %|*%>\
    %<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>\
    %<(zero)%17(decode(friendly{from}))%>  \
    %(decode{subject})%<{body}<<%{body}>>%>
    
  2. Set the environment variable MM_CHARSET=iso-8859-1

  3. Set the environment variable LC_CTYPE appropriately. The easiest way is just to set the environment variable LANG. Setting LANG=en_US works on Red Hat Linux 6.x but may depend on your Unix variant. Try running the command locale -a to see what locales are available on your system. Use the locale command to verify the settings.

  4. Make sure both these are exported to the environment exmh runs in, e.g. by putting them in your .profile. You may also want to set LESSCHARSET=latin1 if you use nmh from the command-line with less(1) as your pager.

  5. Restart exmh and do a "More->Rescan Folder" to make it refresh its cache (just restarting exmh is not enough).

One final note: You may still see headers that appear to be correctly encoded but are not decoded. RFC 2047 specifies that the encoded text may not contain unencoded spaces. Spaces must be encoded, either as "=20" or as an underscore. The exmh message display window will accept headers with unencoded spaces, but the nmh scan program will not. Such incorrectly encoded headers will be decoded in the message window but will not be decoded in the folder TOC.

3. I can't get background incorporate to work. What am I doing wrong?

The most likely cause is that the TK send facility does not work for you because of Xauthority issues. See FAQ 4a & 4b. If you cannot get send working, you have two options. First, disable the background process so that all periodic activity is done in the front-end. Do this via the preferences entry for Background Processing.

Another cause that might disable inc completely is lack of the MAILDROP environment variable. This should be set to the name of the spool file that contains incoming mail (unless you are using POP). The latest Exmh will warn you about this and try to choose a default value, but to be safe you should set this up properly.

4a. How do I get Tk send to work?

Tk "send" lets two TCL interpreters issue commands to each other, and it uses the X server for communication. Beginning with TK 3.3, this also honors the Xauthority protocol, unless you compile TK with -DTK_NO_SECURITY. You can test this by running the following command:

echo 'send exmh {Exmh_Status "Hello, world!"}; exit' | wish

If this fails you need to recompile or learn how to start your X server so that it does Xauthority right. Note that even if you set up Xauthority right, you need to make sure the old-fashioned xhost list is empty. Do this:

xhost -

In addition, if there are any hosts explicitly lists, you must explicitly remove them:

xhost -localhost

There is a Background Processing preferences setting to clear out your xhost list automatically. You need to restart exmh for this setting to take effect.

4b. How do I start my X server so it does Xauthority right?

The general picture of what's going on is this:

  1. Some program generates a magic cookie (arbitrary string) and writes this to a file.
  2. The name of this file (often ~/.Xauthority) is passed to the X server
  3. The X server writes an entry for the DISPLAY into your ~/.Xauthority file.
  4. Xlib reads ~/.Xauthority when you create a window, and passes the cookie value back to the X server.

The specific details vary from server to server. For SunOS and openwin, you should just be able to start up with:

openwin -auth magic-cookie

Another person says,

The Xauthority stuff seems to work now. All I did was declare and export XAUTHORITY from my .profile. I hadn't done it before since the value ($HOME/.Xauthority) is supposed to be the default. We're using XDM. In more detail, here is what happens under the covers...

    if [ ! \( -d $HOME -a -w $HOME \) ]; then
      echo "Warning: Can't write X authority file" 1>&2 ;
      auth_args=""
    else
      authfname=$HOME/.xnews.`uname -n`$DISPLAY
      ${OPENWINHOME}/lib/mkcookie $authfname -auth magic-cookie
      auth_args="-auth $authfname"
    fi ;
    ${OPENWINHOME}/bin/xnews $auth_args $server_args $xnews_config_args ;;

There is a more lengthy example given in the misc/Xauthority file that comes with the exmh distribution.

4c. How do I just disable the xauth stuff in exmh?

  • You can't. 8-) That's because it's in Tk, not exmh.
  • It's there because Tk requires xauth for its interprocess communication. Otherwise, there would be a *serious* security hole, allowing any host to run arbitrary scripts in any Tk window it can find. (ANY host -- not just those listed in xhost -- ever hear of IP packet spoofing?)
  • If you're gutsy, tkSend.c allows you to #define TK_NO_SECURITY, which disables the xauth checks and hopes for the best. If you're desperate, rebuilding Tk with this definition might be the thing to do.
  • A better solution would be to arrange for resynchronizing the key. Check out:

http://ce-toolkit.crd.ge.com/tkxauth/

for how to set up xauth on your server. When you log into work, just set up a local script that does:

xauth nlist $DISPLAY | rsh host.at.work.com xauth nmerge -

to resynchronize the session key.

4d. rsh commands don't work between home and work, because the accounts are different on the two machines.

You can set up rsh to work correctly. In your .rhosts at work, put a line like:

host.at.home.net homeuser

and change the command above to read:

xauth nlist $DISPLAY | rsh host.at.work.com -l workuser xauth nmerge - 
I have had mismatched accounts on lots of hosts, and nary a problem keeping the session keys in sync.

A better answer, however, is to use ssh (the secure shell) instead of rsh. Ssh is a drop-in replacement for rsh but with security features including encryption and authentication. It also tunnels X traffic through the encrypted link and automatically sets your DISPLAY variable on the remote side.

5. Where do I find Faces and Metamail packages?

There are pointers to these packages in the software page.

6. How do you get an X-Face: line into your outgoing mail messages?

The compface program that is part of the faces package will generate the X-Face hex string for you. Check its man page for details. If you have a 48x48 X bitmap image in X bitmap .xbm format, then you can convert that into an ikon format using some programs from the pbmplus package. The pipeline looks like
xbmsize48 | xbm2ikon | compface
If you put an X-Face header in your replcomps file (see 15) then you need to double any % and \ in the X-Face string. For example,
abc%def\efg
needs to be written as
abc%%def\\xyz
in the X-Face header of your replcomps files.

6b. How do you display an X-Face: header line?

Under the Faces preferences, set the X-Face pipeline to be similar to:
uncompface | ikon2xbm
(You might need absolute pathnames if these programs are not otherwise on your PATH). uncompface comes with the faces package. ikon2xbm comes with exmh as misc/ikon2xbm.c Just compile it with
cc -o ikon2xbm ikon2xbm.c
Note, this is slower than I'd like, plus the results are not saved anywhere. The intended use of the X-Face header was that the mail agent would update the facesaver database in the background using it.

7. Can I use EXMH as a news reader?

There are two different approaches that may be used to read news with exmh. The older technique requires that the news hiearchy be available locally or via NFS. Here's the writeup on that:

To get started, just make a symbolic link from your ~/Mail directory into the news spool file system. This requires access (e.g., NFS) to the news spool file system, of course. You can do it for a single newsgroup, i.e. clari.feature.dilbert. My symlink looks like:
    Mail/dilbert -> /net/news/news-1/news/spool/clari/feature/dilbert
    
Or, you can link into the interior of the news hierarchy. You might run into a problem from the MH folders command that limits it to about 300 folders. Change the NFOLDERS constant in MH src/h/mh.h from 300 to 30,000 and you shouldn't have any more trouble ;-)

The other technique requires that news be available via an NNTP server. This technique will presort articles into your folders and is described elsewhere in the documentation.

8. How do I change those default wheat-colors for the widgets in EXMH?

(See also exmh.COLORS for more color schemes...) Here is a set of Xresources that I use to get a grey-family for my TK-based applications. You can put this into your ~/.exmh/exmh-defaults, or into your ~/.Xdefaults. This works OK on a monochrome screen, although buttons do not highlight when you pass the mouse over them.
*activeBackground:			#efefef
*activeForeground:			black
*selector:				black
*background:				#dfdfdf
*foreground:				black
*selectBackground:			#bfdfff
*Scale.activeForeground:		#efefef
*Scale.sliderForeground:		#dfdfdf
*Scrollbar.foreground:			#dfdfdf
*Scrollbar.activeForeground:		#efefef
*Button.disabledForeground:		#7f7f7f
*Checkbutton.disabledForeground:	#7f7f7f
*Radiobutton.disabledForeground:	#7f7f7f
*Menu.disabledForeground:		#7f7f7f

9. What's the difference between presort and multidrop inc-styles?

The main difference between presort and multidrop is: with presort, you don't need a ~/.forward that pipes your messages to slocal because exmh will run slocal for you. The second difference is that the presort scheme assumes that messages are completely routed into folders, either with the + syntax (slocal patch required) or by piping messages through rcvstore in the .maildelivery specification. The multidrop scheme assumes you append messages to dropbox files with the '&GT;' or 'file' command in your .maildelivery file. Thus your options are:
  • Use slocal in your .forward, pipe your messages to rcvstore in .maildelivery, and have exmh do background flist updates.
  • Use slocal in your .forward, append messages to files in .maildelivery, specify files to folders mapping in .xmhcheck, and have exmh do background multidrop.
  • Empty .forward, pipe your messages to rcvstore in your .maildelivery, and have exmh do background presort.
  • Note that the following DOES NOT WORK empty .forward, append messages to files in .maildelivery, specify file to folder mapping in .xmhcheck, and have exmh do background presort. WON'T WORK

10. How do I fix the "exmh-bg lost UI {process XXXX}" message?

First - see #4a about Tk send and Xauthority. is most like a problem with the Tk send command. Second - if Tk send works for you, then perhaps it is a problem with the ps command setting for exmh(psCmd). This is set up when exmh is installed and is used to query the existence of other processes. On Berkeley-style systems you can just do
/bin/ps $pid
While on SysV-style systems you need the -p flag
/bin/ps -p $pid

10b. What does "exmh-bg cannot rendez-vous with UI - exiting" mean?

This is a related problem. Tk send is not working so the background process cannot hook up with the user interface. See #4a

11. How come messages are not really removed when I delete them?

By default, MH only renames a message when you delete it. It is either named ,N or #N, depending on how your system is configured. You can take a few different approaches to cleaning up these files.
  1. Set up a cron job to periodically remove them. I use this entry:
    53 5 * * * find /home/cwg/Mail -name ',*' -exec rm {} \;
    
  2. Remove them by hand, or add a Purge menu entry to do it.
  3. In your ~/.mh_profile, add a line like:
          rmmproc: /bin/rm
          
    This causes the MH rmm command to invoke /bin/rm to nuke the message

12. Why doesn't the flag go up when there is new mail in the spool file?

The appearance of the exmh icon relates to the contents of your mail folders, not your spool file. This reflects a bias towards background inc'ing, which periodically transfers (and maybe sorts) mail into your folders. Check out flag.tcl for the details.

13. Why isn't there a Reply button, but only a menu?

There are really lots of variations on reply, that's why. You should pick your favorite one and define a personal button for it so that *you* get what *you* want. You can define a repl button by putting these resources into your ~/.exmh/exmh-defaults file
*Mops.ubuttonlist: myrepl
*Mops.myrepl.text: Repl
*Mops.myrepl.command: Msg_Reply {any valid repl arguments here}
See the MH man page on repl for more details. Common flags include
    -cc me -nocc me -cc all -nocc all -filter form

14. Are there newsgroups or mailing lists for discussion of exmh?

There are three mailing lists, and an archive. First, and this is important, send subscription requests to the corresponding -request address, not the main lists. Please. The exmh mailing lists are archived at http://www.xray.mpe.mpg.de/mailing-lists/exmh/

exmh-announce
Subscribe to this to receive announcements about new exmh releases. Send a mail message to exmh-announce-request@redhat.com to be added to or removed from the list. To subscribe (be added to the list) use a subject of "subscribe". Use a subject of "unsubscribe" to be removed from the list.
exmh-users
Subscribe to this to join a discussion of exmh. This list also gets announcement messages. The exmh-users list is available as a "digest" or non-digest. For digests you will receive one, sometimes large, email per day containing all the posts to the list for that day. Subscribe or unsubscribe by sending a message to exmh-users-request@redhat.com for the non-digest version or to exmh-users-digest-request@redhat.com for the digest version. Use "subscribe" or "unsubscribe" as your subject.
exmh-workers
Subscribe to this to join a discussion among hackers that are interested in programming new stuff for exmh. Subscribe or unsubscribe by sending a message to exmh-workers-request@redhat.com. Use "subscribe" or "unsubscribe" as your subject.
nmh
The comp.mail.mh newsgroup has more information about basic MH stuff.

15. How do I set up the templates for mail messages?

MH uses four template files depending on the operation. nmh adds a fifth type of template file. Default versions of the files are in the MH or nmh library directory. Copy these defaults into your ~/Mail directory so you can customize them. The files are:

components
used when you send a new message. Put the headers and any text you want in your message. Remember to leave either a blank line between the headers and the body, or a line of all dashes.
replcomps
used when you reply to a message. This file is complex because it contains directives that indicate how to fill in the headers based on the content of the mail you are replying to. See the repl man page for details. If you want to put literal values in the headers, you have to double any occurrences of % or \ because these are special characters in the formatting commands. If you want plain text in the body, you have to begin these lines with a colon. Otherwise the lines after the header are discarded. The same rules about separating the headers and the body apply. If you want to add comments to the template, start the line with a semi-colon.

reply filters - the -filter argument to repl specifies a filter that inserts and formats the body of the message to which you are replying. See the repl man page for details.

replgroupcomps (nmh only)
used, if available, when replying with the "-group" option. If exmh detects that nmh is in use the -group option will be used for the "Reply all" function. This causes the behavior of "Reply all" to be consistent regardless of the underlying MH or nmh.
forwcomps
used when forwarding a message. This is more like the components file than the replcomps file.

forward filters -- these control what headers are retained in the forwarded messages, and how those messages are forwarded.

distcomps
used when "redistributing" a message. Redistributing is somewhat like forwarding but the original message is sent on intact. This preserves the original sender but does not allow you to add your own comments. The distcomps file should only contain Resent-xxx headers. See man dist for more information on distcomps.
    ---------cut here for sample components file-----------
To: 
Subject: 
Fcc: outbox
Cc: 
X-Face: "HxE|?EnC9fVMV8f70H83&AMP;{fgLE.|FZ^$&GT;@Q(yb#N,Eh~N]e&AMP;]=&GT;r5~UnRml1:4EglY{9B+
 :'wJq$@c_C!l8@&LT;$t,{YUr4K,QJGHSvS~U]H`&LT;+L*x?eGzSk&GT;XH\W:AK\j?@?c1o&LT;k;j'Ei/UL)!*0
 ILwSR)J\bc)gjz!rrGQ2#i*f:M:ydhK}jp4dWQW?;0{,#iWrCV$4~%e/3)$1/D


	Brent Welch	Xerox-PARC
    ------------end sample components file-----------------

    ---------cut here for replcomps - compare X-Face-Header differences------
%(lit)%(formataddr %&LT;{reply-to}%|%&LT;{from}%|%{sender}%&GT;%&GT;)\
%&LT;(nonnull)%(void(width))%(putaddr To: )\n%&GT;\
%(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\
%&LT;(nonnull)%(void(width))%(putaddr cc: )\n%&GT;\
%&LT;{subject}Subject: Re: %{subject}\n%&GT;\
%&LT;{date}In-reply-to: %&LT;(mbox{from})%(mbox{from})%|%(friendly{from})%&GT;\
's message of \
%&LT;(nodate{date})%{date}%|%(tws{date})%&GT;.%&LT;{message-id}
	     %{message-id}%&GT;\n%&GT;\
X-Face: "HxE|?EnC9fVMV8f70H83&AMP;{fgLE.|FZ^$&GT;@Q(yb#N,Eh~N]e&AMP;]=&GT;r5~UnRml1:4EglY{9B+
 :'wJq$@c_C!l8@&LT;$t,{YUr4K,QJGHSvS~U]H`&LT;+L*x?eGzSk&GT;XH\\W:AK\\j?@?c1o&LT;k;j'Ei/UL)!*0
 ILwSR)J\\bc)gjz!rrGQ2#i*f:M:ydhK}jp4dWQW?;0{,#iWrCV$4~%%e/3)$1/D
Fcc: outbox\n

    --------------end sample replcomps file----------------

    --------cut here for sample reply filter---------------
from:nocomponent,formatfield=\
"&GT;&GT;&GT;%(friendly{text}) said:" 
body:component="&GT; ",offset=1,overflowoffset=4
:
:---------------------------------
:	Brent Welch	Xerox PARC
    ----------end of sample reply filter-------------------

    ----------cut here for sample forwcomps file-----------
To:
Cc:
Subject:
Fcc: outbox

    ----------end of forwcomps file------------------------

    ----------cut here for sample forward filter-----------
width=80,overflowtext=,overflowoffset=10
leftadjust,compress,compwidth=9
Date:formatfield="%&LT;(nodate{text})%{text}%|%(tws{text})%&GT;"
From:
To:
cc:
Subject:
:
body:nocomponent,overflowoffset=0,noleftadjust,nocompress
    ----------end of sample forward filter-----------------

15a. Can I have templates associated with folders?

To use templates specific to a given folder, simply copy your components and/or replcomps files (see above) into that folder and edit them appropriately. Those files will be used as templates when composing new messages from within the folder or when replying to messages in that folder.

This feature works hierarchically. So for example, if you have several nested folders under Mail/exmh, and you have created the files Mail/exmh/components and Mail/exmh/replcomps, they'll be used (as above) when you're in any of those nested folders.

Folder-specific template files are a feature implemented by exmh; they are not a part of the normal MH/nmh functionality.

16. How do I get a copy of mail I sent saved into a folder (easily).


Use the Fcc: header, which puts a copy of your out-going mail into a folder. You can get this to appear in your messages in two ways.


  1. Add the Fcc: header to the various component files described in #15.
  2. Add a "-fcc sent-mail" argument to your MH profile entries for comp, repl, and forw

17. What is a good alternate Print command to get good formatting?

<Ethan Miller says:> I use the mp package to print mail (and other files as well). Mailp (one of the commands in mp) prints mail nicely. My print command is:

mailp -landscape -twosided -bsdprinter $file
<Anne Possoz adds:> But without metamail piped to mp, in certain circumstances like mail coming from MacIntosh (is0-8859, quote-printable) the accents do not come right. That is why we use:
metamail $file | mp -l | lp
You can get mp at ftp.x.org in contrib/utilities.

18. How do I change the folder table of contents listing?

[See also question 2c.]

This is a feature of the scan and inc MH programs. They take a macro file that describes how to generate this display. The default is buried in your MH lib directory as scan.form, or scan.default

Here is what I have for the default:

%; NOTE: This file is supplied for reference only; it shows the default
%; format string (for non-UK sites) which was compiled into "scan".
%; See the source file "h/scansbr.h" for details.
%4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\
%02(mon{date})/%02(mday{date})%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(friendly{to})%>%>%<(zero)%17(friendly{from})%> \ %{subject}%<{body}<<%{body}>>%>

Copy this into ~/Mail/scan.form Add

scan: -form scan.form
inc: -form scan.form
to your .mh_profile

NOTE: Exmh depends on the output of the scan form to have the message number come first, followed by a character that can be either a space or a plus '+' to mark the current message So - leave this magic at the front (you can change the 4 as noted below)

%4(msg)%<(cur)+%| %>

Now edit the form as described below.

18a. Remove the leading words of the message

Remove the trailing "%<{body}<<%{body}>>%>" from the scan.form

18b. Handle message numbers > 9999

Change the leading "%4(msg)" to "%5(msg)" (or %6 to allow > 99999

18c. Add annotations to messages that have been replied to.

MH provides an annotation facility that will cause new message headers to be added to a message when you reply to or forward the message. In addition, the default scan.form adds a dash (-) to the scan listing for annotated messages so you can see their status in the folder table of contents.

To get annotations you must add to your .mh_profile.

repl: -annotate
If you have other profile options for repl, just add -annotate. Note: it won't work to abbreviate it as -anno.

18d. Colorize message headers.

Did you know you can colorize rfc822 headers in the message display by setting *m_tagnames and related X resources? This feature has been around for some time, but seems to be little-known. Here's what I have in my ~/.exmh/exmh-defaults-color file.

*m_tagnames: hidden subject from x-filters-matched content-type x-mailer replied replied-to

m_tagnames lists headers that have display resources associated with them. There are two special ones, "hidden" applies to the headers that are scrolled off the top of the display. "general" applies to the ones that are visible by default. The rest are just literal names of headers.

The display resources are anything that is valid for the Tk text widget tag facility. The most useful ones are font and foreground, but you can check out the Tk text widget man page for all the possibilities. Here is what I use:

*m_hidden: -font 6x10
*m_subject: -foreground blue
*m_x-filters-matched: -foreground "medium sea green"
*m_content-type: -foreground "medium sea green"
*m_x-mailer: -foreground "medium sea green"
*m_from: -foreground blue
*m_replied: -foreground "violet red"

19. How do signatures work?

Create a file called .signature in your home directory. Then when you hit the Sign button, sedit will add the contents of that file to the end of your message. To create multiple signatures, just create multiple files with .signature as a prefix (for example, .signature and .signature.rant). Then the Sign button becomes a Sign... menu.

If you have Auto-sign enabled in the Simple Editor Preferences section, your signature will be added to the message when you hit Send rather than when you hit the Sign button. In this case, the "(intelligent)" option on the Sign... menu causes messages being sent solely within the local domain to be signed using a different file from those being sent outside of it; the Intelligent Signatures Preferences section allows you to specify which files to use.

Another trick is to create an executable program that outputs your signature text. If you call this program .signature.something, sedit will append the output of the program to the end of your message when you choose that signature file. Three arguments will be passed to this program (in this order): the command used to create that message (i.e. one of [comp, repl, forw, dist, unknown]), the name of the current folder when composition was started, and the filename of the draft message. You can then use these arguments in your program to decide what signature text to output: for example, you might look inside the draft message to find out who it is being sent to, or what its subject line says.

21. How do I make exmh look good with WindowMaker or GNUstep?

First get tkstep up and running. tkstep may be found at one of these locations:

Second, in the exmh installer, specify wishstep instead of wish.

Third, go into Preferences>Windows & Scrolling and move the Vertical Scrollbar from the right side to the left side.

22. How do I make exmh want to display messages as plain-text rather than HTML-formatted?

Add the following lines to your ~/.exmh/exmh-defaults file and restart exmh.

*mime_alternative_prefs: text/plain text/richtext text/html

23. How can I stop my own address from appearing on the cc list when I reply to messages?

MH/nmh needs to be told not to include you in replies. To do this it also needs to know what address(es) are yours. Both of these things are specified in your ~/.mh_profile file:

  1. Add this line to your .mh_profile:
    repl: -nocc me
    
    (or add "-nocc me" to the repl line if you already have one)
  2. Add the following line to your .mh_profile:
    alternate-mailboxes: your_address@your_domain
    
    (if you have more than one address that you want considered to be your address, add an entry for each. Like this:
    alternate-mailboxes: your_addr@your_domain, your_addr2@your_domain2, ...
    
    (these can contain "*" as a wildcard if you want).

    See the mh-profile manpage for more details.

24. How do I fix errors from the scan command.

Errors from scan are most likely caused by conflicting entries in your .mh_profile for "scan" or "scanproc". Here is a summary of what you can and cannot do:

  • In .mh_profile, do not put any arguments to scan in a "scanproc" line, e.g.,
    scanproc: scan -myfavorite scan arguments
    
    This will break because exmh thinks the whole thing is the name of a program. (This is to handle white-space in file names.)
  • Instead, use the "scan" entry in your .mh_profile for arguments:
    scan: -myfavorite arguments
    
Back to the exmh index exmh-2.9.0/lib/html/Aliases.html0000644000170700017070000000362113201227060015771 0ustar valdisvaldis Aliases Help

Aliases Help

Aliases are short names for email addresses. You can have multiple address as part of one alias. Aliases can refer to other aliases that are defined after them.

The email address can include RFC822 comments in parentheses, like: (Brent Welch) welch@acm.org

BUG WARNING: the addresses are not really parsed, and if you have a comma inside a comment, it screws up. Don't use this browser in that case.

Use Import to import aliases from .mailrc files.

Search lists by typing in the entry below them. Hit space when the correct alias is selected. (Use <control-space> when the correct address is selected. That'll work for alias completion, too.) <space>

will define a new alias if what you have typed does not match an existing alias. <control-c>

will delete the matching alias.

You can select and paste out of the Alias list. The selection is not exported from the Address list. This asymmetry means you can select an address, then select and paste another version of that address into the entry widget below the address list, and (finally) click Change to update that address.

Your aliases are usually stored in ~/.mh_aliases For the truth, check your AliasFile: MH profile entry.

Exmh remembers the placement of the window, but not necessarily its size. For best results, play with the following resources.

For Tk 3.6 and earlier:
*Alias*alias.listbox.geometry: 20x10
*Alias*addr.listbox.geometry: 30x10

For Tk 4.0 and after:
*Alias*alias.listbox.width: 20
*Alias*alias.listbox.height: 10
*Alias*addr.listbox.width: 30
*Alias*addr.listbox.height: 10

See also: Aliases and Addresses

Main Help Index

exmh-2.9.0/lib/html/right-arrow.gif0000644000170700017070000000026513201227060016457 0ustar valdisvaldisGIF87a$ò¤¤¤PPPxxxÄÄÄÓÓÓ,$‚XºÜþ0ÊÙ„ 8ëÍ»Váä^eê¢ê#ë¾p'Ï@Ôf˜À p8$ì8·@À ƨtjäa’Ëæ“Ê•Z±LÚ-óÀZr™úõa²âízj `‰xbéÆituW}~o‚(„o1ƒ‰‹ˆŽ-‘N•–—˜™˜ažŸ ¡L ;exmh-2.9.0/lib/html/ppp.howto.html0000644000170700017070000001571013201227060016350 0ustar valdisvaldis Setting up mail on PPP-connected dial-up machines
ABOUT SETTING UP MAIL ON PPP-CONNECTED DIAL-UP MACHINES OR
        WORKSTATIONS USING A CENTRAL MAIL SYSTEM.
==========================================================

# This howto is distributed in the hope that it will be useful,        #
# but WITHOUT ANY WARRANTY; without even the implied warranty of       #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                 #

This howto is for you if you have a Unix machine that does not have a
permanent Internet connection but rather uses dial-up PPP to connect to
your Internet service provider. The problem also affects those using a
central mail system for a workstation and want the central address to
show up as the "From:" address in the header. A common problem is how
to masquerade as your ISP's mailhost to get

From: me@myispprovider.com

instead of

From: me@mylocalPPPmachine.nowhere

Another problem is how to send and receive mail.

0.) Fixing MH 
=============
This section is probably not relevant to use of a central mail system.

For PPP connections you just need to add two lines to your MH mail
transport configuration file.  For original MH this file is called
mtstailor (typically installed in /usr/local/lib/mh).  For nmh it is
mts.conf (typically installed in /usr/local/nmh/etc).  In either case
you put in two entries: "localname" defines the machine name used in
From: lines, "clientname" the machine name used in the SMTP HELO
header.  (If you don't put a clientname entry then localname gets
used, which may make your SMTP server unhappy if it tries to verify
HELO.)

For example, I have:

localname:      sss.pgh.pa.us
clientname:     sss.sss.pgh.pa.us

If you do step 0 then you probably do not have to setup sendmail masquerading.

1a.) Setting up sendmail for masquerading
=========================================

If you don't use sendmail or Postfix, you're on your own. (See 1b if
you use Postfix.) If you're using sendmail, all you need to do is to
replace your /etc/sendmail.cf with a new sendmail.cf that you generate
using the m4 files that come with any (newer) sendmail source
distribution.

In that distribution you'll find directories ./cf/cf, ./cf/domain,
../cf/feature, ... You first have to create an m4 config file for your
host. The file ./cf/README explains how to do that. If you don't want to
read it, here is a quick start with an m4 config file (myhost.mc) that
should be appropriate in most cases (if you don't use procmail, delete
the lines regarding procmail; BTW, redhat 4.2 uses procmail):

# myhost.mc
VERSIONID(`Put here some free text describing the version of this config file')
OSTYPE(linux)
DOMAIN(generic)
define(`SMART_HOST', `myispmailhost.com')dnl
FEATURE(masquerade_envelope)
MASQUERADE_AS(myispdomain)
define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')dnl
define(`confCOPY_ERRORS_TO',`mylocalloginname')dnl
FEATURE(nouucp)
FEATURE(local_procmail)
MAILER(local)
MAILER(smtp)
MAILER(procmail)

In many cases, myispmailhost.com and myispdomain are the same:

Myispmailhost is the host that accepts SMTP connections on TCP port 25
and acts as a mail relay to the outer world (smart host). Very often
the name of a PPP connected machine does not have a valid entry in
DNS (domain name service), i.e. other machines that try to determine
your IP address using your hostname will get an error. Some domains
(notably AOL) won't accept mail from your host if they get such an
error. Therefore, you need to use a mail relay since otherwise you won't
be able to send mail to such domains. If you did not get the address of
a mail relay from your ISP provider, the best bet is to use the same
host that you were told to use as your POP server.

Myispdomain is what you want to see in your "From:" lines. For example,
if you choose

MASQUERADE_AS(isp.nowhere.com)

your "From:" lines will appear as

From: loginname@isp.nowhere.com

although the name of your PPP connected Unix machine is completely different.

After editing myhost.mc, put the file into ./cf/cf. Then cd to ./cf, call

m4 m4/cf.m4 cf/myhost.mc > sendmail.cf
su
cp sendmail.cf /etc
touch /etc/sendmail.cw

and restart sendmail. That's all.

1b.) Setting up postfix for masquerading
========================================

You will need to edit the postfix main.cf file often found in
/usr/local/etc/postfix. No other file needs adjustment.

In the section titles "ADDRESS REWRITING", add the lines:
masquerade_domains = $mydomain
masquerade_exceptions = root,mailer-daemon
You may add any other accounts for which you do not want 
masquerading to querade_exceptions.

Normally you will not want to set both mail_origin and masquerade_domains
as they will be processed sequntially and masquerade_exceptions will 
be lost.

You can find more information on these changes in sample-rewrite.cf.

2.) Setting up fetchmail
========================

Fetchmail is very good at downloading mail from your mailbox at your ISP
using POP3 (post office protocol version 3).

First get and install fetchmail (for example, from any sunsite
mirror). Configuring fetchmail means basically editing a file
~/.fetchmailrc. Here is my ~/.fetchmailrc:

-------------------------------------------------------------------
poll sirius.physik.TU-Berlin.DE protocol pop3:
	user henrik there has password ********, is henrik here;
-------------------------------------------------------------------

Replace "sirius..." with the name of your POP server (your ISP should
have told you which server to use). Of course, you have to change the
login names and the password.

Don't forget to set the file permissions to 600 using "chmod 600
~/.fetchmailrc" (otherwise other users can read your password).


3.) Automatically sending the sendmail queue and fetching mail at dial-up
========================================================================

If you're sending mail while not being connected to the Internet,
sendmail will append this mail to the mail queue. To automatically send
all mail in the queue whenever you connect to the net using PPP, add
this line to your /etc/ppp/ip-up:

  PATH=$PATH:/usr/sbin:/sbin
  export PATH
  sendmail -q

You probably want to fetch all your new mail whenever you connect,
so add this to /etc/ppp/ip-up (will fetch your mail on startup and
afterwards in intervals of 300 seconds):

  su -c 'fetchmail --daemon 300 --syslog;' henrik

(replace "henrik" with your local login name)

and add this to /etc/ppp/ip-down to automatically kill the fetchmail
daemon when you disconnect:

  PATH=$PATH:/usr/sbin:/sbin
  export PATH
  su -c "fetchmail --quit" henrik

That's all.

---------------------------------------------------------------------
Henrik Seidel, http://satchmo.physik.tu-berlin.de/~henrik/
TU Berlin, Inst. f. Theor. Physik, Sekr. PN 7-1, Hardenbergstr. 36
10623 Berlin, GERMANY, tel: +49-30-314-23000 fax: +49-30-314-21130
use "finger henrik@satchmo.physik.tu-berlin.de" to get my public pgp key
---------------------------------------------------------------------
exmh-2.9.0/lib/html/maillist.html0000644000170700017070000000355413201227060016233 0ustar valdisvaldis Mailing Lists For exmh

Mailing Lists For exmh

by Brent Welch

There are three mailing lists for exmh.

  • exmh-announce@redhat.com receives occasional messages about new releases of exmh. The traffic is rather light.
  • exmh-users@redhat.com is for general Q&A about exmh. The traffic can be high, but that's why you use a mail reader that supports filters. You can divert all the junk mail into a folder and read it later. NOTE: This list gets all the exmh-announce traffic too. Do not subscribe to both.
  • exmh-workers@redhat.com is for folks that like to hack on the implementation. Post your nifty exmh Tcl extension here, or patches that fix bugs, and so on.
    NOTE: This lists no longergets all the exmh-users traffic, so you may choose to subscribe to either or both of exmh-users and exmh-workers.

These messages are controlled by the SmartList mailing list manager. To subscribe to a list, send a message to exmh-list-request with a subscribe command in the Subject header. Exmh provides menu entries under the Help menu that compose these messages automatically. For example, to subscribe to exmh-announce, your mail message would look like this:

-------------cut here-----------
To: exmh-announce-request@redhat.com
Subject: subscribe
From: (the address you want to subscribe) <welch@acm.org>

What's in the body doesn't matter.
-------------end of file--------

To get a complete list of commands, send a message containing the command help to the address exmh-users@redhat.com

Back to the exmh index exmh-2.9.0/lib/html/exmh.snap1.gif0000644000170700017070000006232013201227060016174 0ustar valdisvaldisGIF87apãÐ †††€H=‹ÿÿÿïïïßßßÓÓÓÿ,pþÐI§­øêÌ·ïà'†äh–試ìê¶ð+Çôl×ø­ç¼¶ÿ½ p(,Æ$r©l2ŸE§JZ«Ø«6ËÝzuÝðw,.“Ïæ4z½Â ï8|.¯Óïö<~¯ïóÿ~€ƒ‚…„‡†‰ˆ‹ŠŒŽ‘“’•”—–’™˜ž Ÿ¢¡¤£¦¥¨§ª©¬«ªn ²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎϵo›oÐÖרÙÚÛÜÝÞßàá·s°œâçèéêëìíîï¶Òœ³÷øùøðüýþÿžÓGð­‚g‘3K]EH±¢Å‹ŸMt¸/ÁƉþ íÍ’W€žHƒ·6.S™±¥Ë—0-~ìèñ H‡7,lX“&N–Q~ì‰ó'ИH“*]Š ¤Ï¡EkF%i²(͈G¥JÅÊÑãC¬\™ŠK¶ì/°(sz½šs§9«BÕÖ ÙժݨfóêÝ›m>¼@é& J­^Ô}‚mé³G7lb¾#Kö§’­Üà åñ 5¥â»Ž/OMºt·™µÚœZ¡ªÖ¯i³†ä Z´éÛ¸s›97hÁ¶šßnåøxnÜ“µñê^μ¹.§Ÿmç$<¡àµÊkßνYqÕY£º¥&={÷óèÓó ÝüêÁ­ 3FèS½ýûöéÿ¯?3žøþ(à€ÙP7&¨à1ãU·àƒFx‹­T芅^¨a†nèa‡ ~xI9……h¢ˆ'¦ˆâŠ*¶Èâ‹.Ú1Mu`ã8æ¨ãŽ<öèã@)äDiä‘HÉÐ’L6餓<)å”RFIå•Xf©e–Vn¹e—^†)æ˜5’‰e”ÁQ“äšl¶éæ›pÆ)§™L&MÚ‰çž| gŸuÞ è YþI¨Ö(碌6êè£2´fÆI©•Bz©¤pnªh¦zj©žiVꩨ¦ªê¢œ")j§•® +¦³¶*k›¯¾yi¢·öê믲Újd®n ì°±êšì±ÈþÒª,šÿqÂì´ÔV{¤¤¸Zi¶6r«#Þöø*¸áæîšäY»®º8¶›îçú:n½IîÖöªÿ¾©ÀÀ:Œ¥(uéÑšR™6K•U©NwÚ#˜F¦ iMš/¢‚Ô¦-MgIÖÉÓ¦:UH>R‰4Õ°UUªF½èUƒC‰®ò©` +ŽB©²šõ¬h5«•ÒÊÖ¶¢u­n«\çJ׸µ®s½+^÷ÊW¾êµ¯iõšã'Ö‚ÕO€U+bËÖ(1ö±UldߺØÉZv¯Ž½lW"-Ãzö³  ­hÙtÒ `G„J­jWËÚÖºöµ°­lgKÛÕÂl]ÀisTÛÞúö·À ®p‡KÜâ’)¥½Qnwþ;ÖŒŽö¹Ð®t§E)œòv¹ÌµQT§ËÝîz÷»l¢Tr­„Ý^¼èM¯z×[ÐXW¹@€|Í _öÚ÷¾ø}®xá÷©%É·¼Ùm• LàøÀ΂<àü:øÁ¡­îmáûßù2WÀ ΰ†¬à /ø[Š ±ˆGLâÄ&N±ŠQ¬â»8Ä,~±!G'ãÏX…6ÎqŒm¼ãû8˜5þéIRáÿÒÃN²‡;¬äë·scm”};å1UùµWvm–½´eÙvYJ•° WIä"X»Ÿj²šÌä5ÓópP~²måÜÛ/gÉΩÅ3¡ôL%>K™ÎX 3rùKþ^3[ØYnv3CÜ=5 ÀÕ\ÝÈô1E¹Ò{4l1íg8`š!žÒ§¯ê=’ÓLÚ¨'éH³Ì£¦´¤ŸŒjTƒú§ÖÅ®nwÍkD'zͶa£›lF'ÔȾsª­LkÕ–šOœ–s¬4êgS[ÒËn’µEMêH{ÛÉ·§=‡r?iÚâ&õ¬Íen9„[ЉÒ5¯ç=$ÿZÉÅ>ذñ ir£›ÛéÞÒ¥­i,¯ÎæøÁ-†'tÇzÛ”vu»ÓýéS'ûßÿNxŸÞ­oOÚÖ_¥˜{'Ì%$3é`KØ£­r–+ å/y±a®rcs+€0Ÿ¹Ìcsþ—ÌÛÕžôª+ýêW»Õ§µª‡þn¦OüÖì6úÒãÀi¡K]èãŽvÔ—~ô€_ÚݶæzÑ«Žõw<ìXŸú·W-n²G,àMO5Ð/^öŠ[]ìi{³íðn!K§59ÊyÞó`¯|ð:gy¾ ¿xì[ç=¯ùá@W«Ùa϶ÆÝÝîf‡óØ®uÛ=¿ùµsþôÚ~ºÙ½–pW{ïå{èÛ®yŽ{Mô Ç<Ñ)Þzok¼ÝuŸûâþôŠÏ¾ïQǃÔqMòøúÌ‚—üÉïòÄ^æÕ·¹íštýȾæúö·æQßzp³Úõ¤'ºªq?üÎ'ŸîOýø‡NþÕþï½ëÏO{¸œîHÄ÷yYÇp8mng€»bmWtr·~£÷~í§u\5hƒU&Îghæ}‘‡sfxˆ‚àGxáws#è’×$(|M—y´Ç~Èp0{¨‡~Xƒò÷‚Çç~g|×–jú×Bèƒ@xƒÙVmBx€¾G„9hq±÷{ªÇ{óup6ƒT(r¹–f¶iÖr”—‚(¨‚ß'†ÝW‚Ûw}ß7yŒWy⧃—{H¶‡ƒH‡i§tV·ƒ-xyqx…÷„®§mA8|VX~<(ƒl7ƒ¨‡N…ªç„ 8„æ‡õ÷}¸zâbêÄ/e¦×…þ$è…'(Фy'‡}Âv78÷…dy?׆H‹­&‡´UˆweGƒUwˆgGm¨myŒww‡ìÆvN×u~x{;¨~nwŒk—Œê§‹²ˆv÷|ÇÆ€ ˆŒxv¸(‹Ú˜wÍgƒ˜…Ï} Øx÷–dû¶Ž¾×Zäh€êF€}Fz²fi'pù8gŸiï&X[¡o§…Eƅ癩ë¸aíxoÿ(eu·¾˜qÔfVÆlýˆ©e™g)p[É|c–-¸…ŸøN éf ùkáôc0 d1™b=6“2V“/†“6ybδ“7‰c?Fc>™“=éb~w…æþ‰BMC”Ei“•FÒ”+ö”<&]bæU&i†:I•-ö•W)•d©.`YbbI“X©‰Kʼn\id)™–gIbBé“ey—5—"&—h¹–æø|^)3"vŽ„Y˜“x™˜Š)'û…”'yq9-ƒi˜”Y™–)_ˆ¹˜š¹˜YÉYjò˜]™½2™—Yš¦yš…é”A’h›)?n¦^¹‰`špÉQAf•2†šº¹›¼¹›0™d|©—CœÂécm¦dÄ9“ÇÒ™n”(i›ú¸‘¸7½YÖyØYa™ÉzÆe&7\åšÒùgYÖôàœ Zre#–îùžðŸEþöcÝY‘ãYŸ`vœÀyŸWž©”¶Buu'ˆV)Ÿz š f“yvnÙmÀžæs¹ƒ„wF‘öù+±Ù–³ù–‡ Å×zL Z¢&z¢(jh fÊŸóˆ¡ä©’ Öxš£ôHjË9r%‰ž¡ 0Hš)¤B:¤D:ŸÆ))\:¡ ¶‘6 …õXž¼B› P5bEš¥Zº¥\ú|1éuyŽºçÝÈq«8s>G£Å8vdW{j‘þÙ|瘷¤]z§xš§zj¤ô9¦qXˆKj}#¨¦U¸ŒMø‚Õ˜S޲¡çI¥è8¢$º§’:©”Z©ç8“Æh¦£¸sþaH@…ª{S'vÈyE¨¡:ª•å4åN2å >â= ÕCÌÅ÷äd^ÂÎ.× ÑÞÞÞã5¾ã ¾åVÞæVNåP.ßî-âˆ+ i×ÙU\怮gŽUð̯ÿÕáqÞàZžèWÞè?Îåwézn¤þK¼ÃA蘎™lvæ,¾á‡NçŽê>ê‹Nç .꥞ê]¾çìûÙaœéd›ŽÇPë¶~븞뺾ëµîß·îë¼ì½Þ@…¾±„=ê<žì]>ã¤Nå9Îå>þæ>¾ãKkdZë—ë€.ë–΋ÞJÝéÇ.ØOþÞSäÉœgÚ¾í³Ž¤ã.îííD Ë­µÎÚú¾ï«]ÎÝÜîGÎíFïÐîcm£ØþÒèÜéVïüþðÙú,ìŸëëïÎÒnËËœ Àøª€}Æ-Êä-nèò.ðfðc¥=¨‘/áO  ïä(óø]iÒ笻íþÛ2­È¶îÈ_—ð§KÛÜHôAïç1ýŒ«Dò^ñPõR?õT_õVõXŸõZ¿õ\ßõ^õ;O‚é7ŽÝ+Ã?¾¤:eñ«ôŒ|5¿æˆHÇp¼IOôâ¨ÀKÌÆF¯ŒðWÔw»ˆvoÙ€ú×FHÀAŸÔŠøpcoÄX<€ÛX†Ø·hj8¨ÌºrÓçdkª÷ÞÛH/mÓI×kjÀ]=ªPÈ-Nßð…*÷ßê›o‰8h¿`îú«ÏÅÖ?ûÑ*ø†ZÖWüÅᎫcì†klë´ ù“߬­hC Y׫玲ö;üz¡¼OýlÄÖøžú Mˆˆ¯Ö…?{°¯‹1Ø‹dOþXûu¸÷sŸû²뮞ÁÇ—tßßÒë_Ù¿;‹g}cèŠû¿†Ë_ø¤1€^j¯¶ºî#¹ì+?¯dzÛ^Ì“ML=‚à+¨} B8@ÃÊÕšd$œåsÓ¬PmJt2«’N°+‹û„feT©Ó”άBÚi3Í ¿Þ˜Ææë¿?78µ³»3´tÛª·þ{À!¤PÄIœÐ£fJÜHÓi‘š OŒ'Fg.ÄЬüþÚ¯5ç8 !tÈÂÕPæ!’ÆhB1ïÇ WLE†"Bò”!­”Œ' š#‚º¼Gì,C‰Çî>ô2†…¸I!Ë«…£’ÔòH:‹‘ÓI0%H‘E)ïd²˜+±€“Í-ÿ ÈŽd9dÑ1Éô‹5îöñqM ‰lçM $O³Æ;!õ'!=´Ð?KþTv )QEýdôGkµ1Ò4ÔMK]bôË5pU%¡oZø# f c+ÞÔ#Zk­•XÂÌãÍjUé#ÏBš!…kQV'»5èŲv‹u…x­E^c¼õQ[y%+GJ 0b`‚ÿô].É¥rS6—av™jqMxY?mô‰s]ÖÙ[m6Ó.õ½øˆ£pWVE>$â/FØái%n—„eT}XKDü-Ë×3.øçKñ(÷e…Í=xè¢]Pz,&cb¨CZÚal[Öua”×àÜoÄ…™Ë’çÄúY“·Èsì[™0›”„ùt™Ü·sNnDåÖY,€þ÷ËæNí-šã£ENúo‹ GTl°›^zãÃ5µðÅ?¶:äºef:k·!§;åÄeñ¯¿ùópçöXÞ®ïÆ»ÌÝzNfa1‚èȤYÙ©uã-ß#ÕWŸtG 43¸•1P/ýï—§ÙÍï­·sqÕŸ–ªáõYµÁ¿t/Ýk{Rƒ·šÖ¿yMO øJ Èö%@}% € xÚÓÀ¾ëÔãWÀÚLìV• 9ÊS#:U¢^e!›¤„uZaƒZˆªL(… ±Råø 0JSþ<øªp„j­ G¡аˆzz¡¦†+ˆ„r y¶pç>,Ì'ÄSº€Ñ*bœO½ˆžï$…Œf,Ï˨”4Fņ½Â¡~t¸n†‹sä#yâÓG?¾q=ð© ¯ˆ,v¨‰dÛØÈ7„|LóvGˈJX˜U5n…%ZûªÞÄh!Ab _ÄÈe°übÑ2© cîCdqŠÛà®ÙÕñu³{cÜÞÈ9 pmw\d ÙÀáïLÞ.j“ ŸFö»÷^8Æð†7ÑÜ,KâËcq‡µ|fþ.‹Í–3›ÁܽÏùM¸û˜àHF]ç8ÏIÞ3q¬ç?ïYÏÜÍql ]h?çFn2‚i¡à.΂Ø3Úñ*x¶ÎVØÄj.q›!Õø¢vÌ`ötŠ!j-o¹Í#õ§X½™å7ºl£Ýàjlh"úЇþ³›ñ·K½p‹§Ú½p†5Ü È·ìþպ݃7½M¾ëaß{Þ+ï5 Q¾o—ÇüØâ+”©§ÿ…é¾8o µ)L “Û£në‰þáöj›‡Ñ™~‰Š‹º[.î9– R®ôÑ]ïþq¢YóEYÉFr¾‘mv #»ëE¸HºÙ8w®†ë|›¢tú2e±¯EYÉ:Y·ÌÖa”¸wSÑ}­v×;ÄóÞx¸ƒPî‚í/X-yÌoµíŽò±*•äÆ5ôwýãk*J¦¢~°Í|ë]ßú¶[¶ðަ}ík/ðØÙ^÷»ÿ¨Íyÿ{à[÷$ ~ñ¿Jß_ùËŸh@ ÌxF_úÓ§~õ­}ìgþŸ™²ÿ€ö½ÿ}ð‡_üã';Ì|Œ" YGÚ¢÷¯#þ´š?>@V,¢ß¢ @ý³Ñþó?‰@ @{2À}ê¿óÓ?‰Ê=¹ÀKi tÀ¸˜@âÓ ¬@L Ä?Db@ˆ¢@¸ÈÀì@¼0AÄPAü@AÈ`AÏ€ÀÁ‡"Á·€A¶ÀA ŒÀ½ÐAµðÁtÁ@,|¥~“²°‘ Ì—µhB%< f€ÂEé—ä 3",´BÊÂÎAçËЯ± Cápµ´H­7[ 3®²PC4lüH¨ñ` ´•]Y_¸=´ÃêC±†=¼þüC>¤Ã7˜ %HİpÂÈø@3É¿Ïæª¶°DKÌD³ØÄ2,7ÄÄÈhC4ô3”¯SŽPÄO@ <ìC@@D:Ä·˜Â<ĵ0D”Åë E½ÐE,DÆÃÃJüDQT OT 9\Æfí¥JE tÓUM‹GÕÔLeUDmURU:¥ÔT]%[5Ô]=N5-UEVQíÕ`%Ö_å>¤ÌÕð¡€nB‚krVn‚Ös’Vj¢Öu²Vx‚‡bL eu%è‹Öo­& ð¦qM§rµ¦sm§t¾û“L#§Dâ]‰bý|^·»#Ÿù‚ùZŠý ª Ÿ=fÞþWÂ]5EÖ:¶c‚AØ<>ä¢ýã VS\ CFdHAèM [ý_ú]bßµ ¹å¤7Îâ¤õÝ;\d¤DD¶í]ÉèãÆPe¬uÐF‹Xõ_Me þËå å©…ÎUºe?žå ~ßZ¬Z_æÎ`åÄ0fbnA‹¥äˆÅE@Îd²eÙ"Ý*î`nQdNe­\ÇübÐ-ÒoNæ5nbÃbãu^%Ý~ãmn\ÅãÒ…gy¶äÜåàã%Š.¶g¾ CnE‹Í­føøfo–fÖ¥MîÜ*_¦Fa“–bqá¤ÌWæW˜ÞßRZáI^Ž`žxj±ÎdÛh`fÎæfÙf\Žaãå]^†æµ¦à”œë”êãí_ c‚Vç®è…Öá"DÊX«-ßø½ßÃ=JÀÆå(NçEŽ 8Öeñ%àûõfd”Žl.ªI~é]žlDAeæH>nDîí³¨äS¦Þ'¦ëþÝ‚FeŠnÚÕžn¹(ļ`ç«-¼gô½‹Ýîî}ÞVÚŽe›–Z€Ûˆ®j™¦YSfhò~ï¡Æn·¸e^oœ•jÍvï\ŽÛ–.lµ V»¬_†ëšlÔ&ãnâ»îìEgl~çìÞk彿˜•pÄý[}6m GèÍNèvÖðåubwvã.¦ç%EÚæŽìEhÝåpcñ™í§m{fg$Ì6kPFm"æbuáÑfi òZÌì´^ï±>pìÜY6ò¸Ö_ 'ÞÝ…ê&ë"§ê½mPîòÖORéÓÖÝ)¯,7nç¦o¥ioï*'0â2¿êzþ`NiþoîEL ŽêÓFa•îä8ÆG6b 6J÷rÐ>Ü)–_ºÜqm$•h -nßnå_væ¯ÞÇs ¦êC×òÙeqËïÀvjÜei¹u=‡Î —TYV_'夽Mþd¯îô·Fg“Æõºfâ#OtZ?I—^î­Vìëö\;ïéB„\ðÆæ6_öçÅ–q·Æ_I/kð¦é¿óIÇìOño?ñ ¨n,vçßÑ£ÖbtÏ[œ¦q@?w >b9ÎjˆEnʶu±Òï›ínÂc7‹GÖ÷ýF°€¿ï©îÓÀtd7xˆOXå&xÚžpòN÷Z—gNFò?æoL®oêpGþ Ø®îèÐï=txŠwîi7õ8Ïq]Ïvë•y>j÷[_s… SŽ]“kG²ï‰/ ·ï’îOŽù|ngk6ñ,”ïhWúŒrw÷ì ®âÕÌñ õø~î+'q¼@qØíëoí¬l•z'ãQÞö¾l~7h<§w3çuÜ(óS÷sì.ë‹®û]×s”–e‡ŽqÆvô{&sˆÎó0×èqœê–gôwWîx¢mì¾é`wy6ÞpÝFÛ¤VõFWðhÿa<×î¥&ùžsŸ×b/>ý¦ÏåÀ-õwü€žo>Åw`Âyª½ð¯¶o¼ëQçrÖ§ `/é·f)æBþ®zöþû$öu™Ýz,W~W?éJuŸ÷}/ì¿¶h~ß• '‹Ã^ßeÏÏf¯Ë«‡÷ñÝâµuìãxúB?ô¢îì‘Äku¯ýz—ÂÏûÛ·x8`‚#§­6oM=–…—¶™’IqgÇ¢«*–±K—nFÁ÷ýÎ%4„Æ#2©\2gÌ'4*e9§Ök {ºi­ÜçWÉwW¯22,Ìv=\í"¢ëv#í®·ç÷{ù _à`ÓˆaTŽ›O\Ñ]¢ä$e¥å%f¦ææ#S¤XÈGa– ª™Ð)XÓê‘k ¢WŸß©œi«î]mYÊ™â/Zîkl§èOÛ£ÒhZ¬k…þµ­ì™eUÒìV—·*ð7r+ž8,öpºðŸ/¼Ÿ'h›(4;ë6ÿ͵“^0Ì(u¡ÃˆbÆÜ‘@ ?UÖÖ¡zèDã†.UŃ vLXŒÉ‹ Žcø"O°%1Zãˆ%/ƒ&uéT³¨™£|`þU«ø/ÜþgΕ=b\„ZÌÒY0jÂxŒŒ5~݆}T£©býCÞÌ¡…âi¦©Á‚b¦øÅi¬€nÚ_§Yâò_›i…g+—ÅšÒX—JZj‡ï{‚ qÔiç«Q¨Vª[×Úw_["ykbˆ®çU6²êÈcxò¥´Øµ™¤!¹ßî8Ÿzñ†ÖYŒ•ŸˆãJ$ßj]ɴߺãRúLý~k‚œt¶Jí¡‡twb†q;±ŒùŽÅ¬gÑÚ{ñób•²¦Ø×Yµ\¯XþÑÔÞn6Øìˆ.')QK†h¹Š7dÌ.½œW´¡<+övo£—aà[7}Þ^LU¬3Ú»J lÚ^Wn±³¦9æ—2Ÿƒ(7z··â™#À3I{ô“CzÒ>t¯Hû‰!û¨æ¼s¹.K Åm­ºv*i0H¦‚Xí.úß‘»’ì¶„ô†ûâBc_ÝÛƒŽ oT®óú¨·ªJ>3-Ҳ뺾vTâº>§ð7.ÿ_¬2hßéÿM? ¤òÿ?h‡½- }±ÛŸ¨À2°õk]^—¿æ)'mSZ‘²3<ÜÍr¿{”µ8þ'…áîkâÚœðH¸.íX¼â˜"µŽ©ñÁ<ì”4P‰l`£Oûè¸@X®†Ôã!ªþ¶%~í}\Ø §¬vH‡xáºâ²FhCûÙ…BÀgÅ\­B5þÊQ›¨‘]HÄÝÊЕ-‚¯âëÜñ¾§¼’{…ÃAùæÄ·/†Ñ=£˜Š8˜šÓò^'ËŽtH³±,ÒD“XùáÌÜež&MHá« ¹bÄr•­[wñ~܈²Çé1•¸\¢‘27´ÔA‹‹®3Úu¨>ŽM‘!îaá¶¡Ifl£!/eøþ­-m3ÞDá7¥H¡%/•LÛÉΕ—™­mu³"Íl&¯MÆvŠ Ã ƒC2!ðQ³,Õ„M%š”?³1u™#vxgà|¨0+Å•3‰ädYË(½Ò­±dâæÎd‘ÇµÈ ŸÆŒ 2)¹Ì„õ¼]KsdÈ#q­`Å›QŒL4¡\o.%ÂæÉêÖ®›º¦š¬ääL‘—ÔÒå´,63*ø2Gé馎7éG·|2I¥ýt œÞçD,‚‘•bÓXuU4|ìÓP_-+\㺧´Êu‹ŒdÛ Æ•Öµ¯~ý+`­°Ö0yµ‚¹3­š, ñΔL  ͪÅþxððwÜDìŸ%ÙѱVIÔ,Y+ ®6‡A¦=m%ÕPÎÀ‡j½¬b-_H×-ñ³]*Äe_ëÁ4‰¶eÜÛ,<+1XÄ ¶¸|e-‰ØT@S^Ë ˜Ì‚gU÷Ýtº±Ø©®zØ—õ‘ À%ÛuÑåÉxÅx=o£ºËFsÅó]ÑÕjýîJ'HÀê&ö§Ð¬·Éše¯½ÐÝoHg«ŽéÕÖŒ°½ÌjßÉ••Eq¼ªMg·>ʹmÕŒŠçÕãÕF)9ĉ-e©‚ ˜„’XÐÅñÂÍåå/ JåM•¶Û<Ç'¹©aü¦H¡õœn"×T„¶èvF¯¢:ôÒ{i” !-}{D€þ^qÆB,±3ŸkPàZ Å<|iv6ýÔœµLèUM¨åL©ÎÄÊý…ãâZ ò¸±’L aО-œZcùÜÌuÇZêsOµ»SÐØ‚L,öÌëã–-n…ÎN~ú ÏŠÔi<ÊrððFÓ… 9õ ,³Ø'mŠúÏñµ‹tÒËÕâÈ-\ý·@»ÚRœŽä|=Ýåðº×¾þ5°ƒ-ìa»ØÆ>6²“­ìe3»ÙÎ~6´£-mh¿ù~ÒJ²° m"h»ÛÃ@a¼mps{ÜäNN·Ïmu;Ùì.7¼ÑÍîwOÛÙô¦7·Óm|¯»Þý÷ºõï`óþ›×ÛîuÁý­ì„Üàþ†¤|ƒ‚m`Ÿ{Þ„)8¸É]ñvà¿8ÁÝ­œ;\á wÃ}p¼Þÿ÷Âq“K{å3¯wµ»xm][Ý>ÿøÀaþ\åEO¹¸3^ñƒ+ýâD—wÇþs§‡›éOúÑSþk¬—{ÛúÓnp¤ƒœéQ—zÌYŽò7<éâÎvÕ5þvsÃ|îæ^ú×ÛNô¦ç[îf·Ï­®w|“œëë†8P 8q‚¿<ÝJ÷6ÉÏ.ôºK>îS§üßËž÷|·<ì€çøä^öÑ»ðCï7ß#?vŠì®gyÏA/õË›å2oý×?¾÷Ö«þó›zîE{Þ ÿóè&=ê/žócâcñ[?>ìAü ×}úÈ7þðg?yÕg_àÛ»Úõ½{´3þílO>öÅ.ï¶SýÀ×zé¥ßrê›ÿö}Ï|çQïýèŸÞì¿ûôE^àáŸãÍŸ×!Ÿ Þª(ϱžìQÀYß½eÇÑb^N`×Q `»y^èÍ_n`ØqŸŠà f^ ßËñ_ŸÇüõ^æBŸû­` ßïýåžÍúiÛò¡Tó5àÖ]ýÍ ùá ß9 Þ_è Ráºà éí_NaÿéŸJ!Âá÷ùŸf!üYÜþÚIàÜ‘]â]Õ•ÜûÅ!þ áIáÒQ]báÙÙêÝá­NÄ1`ÐÍ%¢"."#FÛÊ}Û±í`.â#6büA %^á¯!«!a&~"(†¢(Fâ(–¢)Þá)‚°) ùA«Õ,Æ¢,2Ðp½bnš¢L5ÈGYW©aÖÁÚAÆ$À˜eeWƒ ‹:,TdQÙ1Âö Ñf B§â§mÊ?¡MÞÈ –ü¢4× ÕŽ3ž• 1Ón:>–n;†#8à 5®Zœéšãd£š ‘=º—t¹‘>êT'õˆÊ´˜6ÄÔƒùc£`M]”ÄÑK )š qÐ!${ ΂ÙþÔLE£ ’ËhŒ¦ Õ­âùØbXàâ˜é×ÐtŽ*‰R½”™“]Ìp„“n=õ(Ø4õDU•£zô‘ÕØŠIvÜ’QD¼#XdTk!ËAÊ0qâ–P&qJiGÙWdÏGê¥+–'¡ú¡•“Ñb‚*'´Ì‚é(æ‘f6Tˆ¦æt‡x–å‡áĪt梾’&Ž9ºèX(¹ç‹µo¢dôTÓ>ÆfˆÖêdâ%6ÅX*9IöÙ8Uo⨠fqú&@ÒYžMѦʩÂgªæ§}æ+ué«=&³´ê«ÀìvJ+aé³Â(Á.,Ã6¬üë(þì•é´^ezÍP¸ž£¥c¥ÙzbņzcÆ„ê°l£b¥ÈbìÉR,-I(HÞk–j§ÇŠéÅpÍ8JT"h7tìkÍM*(ˆ®¨]É;ZJ‡ªl2p'ÄÎÄ>YLj”ÓÂ*3Öfê쨿T)ŽÊZ9d”óô—“²hÈ^דZØÏx$s‘GÂZó<¤Ÿ#Úêdu¡Qw}+âU|ƬƒnkN~äÀFDux-å‘nËÖ”’™}ë’ù©€l#Èä ‰ùír mÆöª›Ql†%R€åF1¦ªÁ™iâ­•Ú6vªXjêäxW¤bˆï,R&@jŒøªáؘOEÙB=®ZÎìãþré;½)£ åSª‹ÏÜ(ƒ^.—¾g+6í[Å“Šf¨\؇VÖ짘nPùäš®­k¥nYõênâRdî®±.«èLŒ¦XÒÊÙê¦gzÎørèY› ªêƒ”èFz.ÊÞ¸2ë>ïݘ¬8०…Ï:é—¢Z A^fs.§HùE¡µìgMO‘rc¥EÙä”’E‘˜@ƪ*oÀ:¬§‹ÈºIz¯¿êâë·ð1° ÷ ¬òư ß0¨-- „pþ"­báf”®¬ÿþ€­hј€íÖpgùúâ!pŠöLøV³ã GìÐ-*ý­+qÔPmš}™ãþ風?“‘ž™ÎŠZe²# èð ð°øª`þØi4顾­’žðôo¼îÒÜÆ©juR¾X×ÕB¤¶¶«ÇØEºí!ÿPdà‹z©—¥P½&¯ˆåmß:prKËÆhxÙ¥äúL™õhô‡‡n$BÁ­éØJZ¯6þÍR˜ž^ÒQ)n-&*Gå‡Éï ‹n‰£°b(žv±nN¬‹= j^í6SNMCXÞ‹Ø™ãÆéO1 ûʪ/×9ŽÍ\1ÓsÊXß Dq¯â¶.ZYYcÂÒ3ƒ&K†™·º¤Å~+ôÔì,c±â©Võ®m±}óV©ð,Èqy© VRþjþbë£á$C0 ó–ëJ’Óñ6ðR!¦YÒ­Dº’¦)ðí¾Q q–€úñòŒëAò™×%Û-Ì&,ƒq­ÎQMk™ #t&ç´OñOc´žó×pP5RÛ'‰PJ6/ ߢK£ôŸi­OJÇpróBqà@qѾiö*QDZQË©¢ŽlŠˆ&kl°¾®Æ’0vž™ÿÊbF1ö19ñ),õȱ!?OS^²Â´æT™d!ïìEûâ£ýhý†2‘þØIbmÿ0"0I[–’vp¨Òx6µJçË‚p +ddõÎÒ(#šURÑbun Ì)þ¤c2ŸÞ©à¢ñ% îæÊƒÛZ.áJ͸Veò$Î>Ïê€îü²°R&—ÓRÓawêêï¹âG3ÏŽ3¿äjzjøòmÕñ–C<‡Ì¡ÎXŸ"«y›ªbWðAŸvO×.E8¯­öbM‘±7>k5\V²6 5cw… f77TTß²±¨Xkf’f)7ãÞæ‰’¦s3M;è<èt÷¢çp¶Gkjm£ãlNv7o×õpð¬š+%2dTmUƒ+ öwl±ÆY3uZ'õ¾6l:ù/ëÜs 3‘'¹’ÿ WÛ’?9”ïÉpÛ4u=±‡iå ¸^÷+·Vtþ_s,Üpõ7úI.lwW[5Y!Y2ñ“`ïi:P1°ãUN5Î 1€s9_çù^ßõŸì2ö6( ËA-¶UjÁ9?†*pb[dgÖJ‰J·4wEÝ6de·jŽ‹-;+ÒK—«óžŒ7ºs-#ÏIÎL§µ9”,oUrAZ0uo99ý¦öòJzWr*sºÁmo_œÚ³(¯sÃLEfTDvƒS‚)·4K yæsXÀ›‹ª«:ŠöㆫÒ%'£9w·ç~wr“9IûJÖ%d«ë<ïúT(nV½oIó­<ê}öY{ÓŠr±«Èœ-ˬ3AëôâJþ‚›Îõ_&;[ËöCí1·ï½«Œýiòd°û~q¥Y¼÷ üh&~>L«û{‚:±^t8¹_jF—wÅ[k¾ËõcÿqŠ_úŠ_g‹ ¯F£Ù»,;ŽÛ®»F¼§%Ißò‰s/òÊ´sôMÉ»z”›Ãz¹M—xV/‹JÓ;ýÓo½­‰;š`µ ê¾3uÖk=ן=ÚÓOÇqÙA¼=ÜǽÜÏ=Ý×½Ýß=Þç½Þï=ß÷½ßÿ=à¾à>á¾á>â'¾âþØ›@µÇñâG¾äO>åW¾å_>æg¾æo>çÃý…ï€(¦½è>|ð(’>êþçŸ~ê·>ן6뻾ìþ?ùê‡þìß~’þíã>ïuí‡bïÿOë>ð[Áñë‰$¿,ò;ÿòÏ™2 ÿÙÿ>(^ó³ÀóCAö[@÷GÁ÷Ÿ@ø{ÿtÿøç3õ§=ñ_¿ñ7ùsÿ%˜ÿû“ÿüS8Õ§¿O[ÿ'Šôó?(u&¥õä*e¾˜ÓBÑëÀÎB/ïc±–µÊ˜¦ö®õïý‰Eã™T.wCá …: Uë›Õn¹V×,¥ £@_pX,3ÕòyýRÃå¾\æÎÔïù}ÿ0P°ÆÀ ê ‘ªk‘±Ñ…£LÌ­-’®rrRòìå²RG®Ž'ïÀt0Uu•µÕ5þÕ0*±‘¶Vk-Ž-m77¦ls&’R“‡7Èõu™¹Ùù9µqj @Ñ6»Ê—3˜fƒ22¼8¸³}ޏ·Ôú>^~¾&¶@JÚ[Ûö÷íMÀG%TŒÀcÜ?A1$Ó‰9”ѳxcF%ÒáÛ§M"­Y4º"UeJ•+÷ØóÈËHF2¯°´ygN®8Vy©e¤“‰Š†ÒÔwkgR¥K™6árÖÑBE©PùÑ€S­[¹v•דZ¾,A‰b3ÊålV¯kÙ¶u«j5©2i-z%í[½{ùöõöçØªeñšµZ%¯_Å‹++V0bÂVê–Œ´qfþÍ›/Žy*eâc^&ÉujÕ®c•üvl»¦±0ƒy›ËÜ»éæíè÷­à$‡×.Þ︗äÛ–óÓ+¬k²¤©‡.»æ²æÙøÞ³ûw+á““?n¾8zñWÔoÿûýú,Ý[£¥]™jþ‰˜yª]€¼xô-·ÑÃ@ÿ–HpWq  ¡ ¬4ÙöÑCþZ9ð? ß‘°“0 Pñ‹p‘°¾âÒêM;]‘‘WqBR #$òD$STòÁð.ü,¸º±-«¢ɃÁ¡"ê!‰p@Åȧ*bÁÁ‰ˆÀ2@-—$ðŽ1ÈþÒL¼L’MÜô!Ë!* ³Dú¨Á0Êú ò”UЬdÚéò)øÄÏ4íÔ“LIý‘MŠ€P¦ÌKëi'RD ÅteÆÜ“Â6›|n@»kÊG…¥RQï„TÎI=Ý5ƒGuå!O#-õ×ÓÔôNSå×\C-õ†9VÑ:eÿ„R¾-E%Îh‘5ÜSÚŒ³WKÉSMOUU•W0%•6\tg…7]Qíd×Ü}¥=€ÚhûŃß]óØÜqÅýàe×eÔ_‚éeøà‡Ý•8j÷´`SÊwUÏäêÖ[YÕ|WS|åWe8 .ߘï-vVà\™ã_eþ¶9Õ—A†¹X—)J9gƒçúR„kæYH¢/~âš+Všê™™&Ö‚q–·i¤ËøV`ý”ÂU’³{k—xh/“ úh‰ÝVûb+ãuT]¹«~Zj"žg£õ][Ë–-u»Ý¨k=0åÄý}9áže{5¦fe»f›c§—ÂÂV¹5Û “ <çªßëqù†p«inxðÕezq•®îÚO‡ÔãÃw/VsÆQoÜf3Vwo„Qüu¤sçýøÈÃÖA[²G'ÄþÖ.:uʶJðÿV~îg¿¼rÅc§=mÕÍŸÞv¨—žv«ÉOúvº=ßÿ]ºr^ïÒ†þ¼¢¯k¨ÞõzºŽltß²äh&pYŽyûœ½¨Á„-zåSò®¦t‰ðaü]ÄÖ—ÁÞÐ _¨5æ+~7ìÅŽU/…É~&œŸíTö½ZÕˆ{µ‘U…˜´ÂOa+<º“á„t¤*©{Ej¢|µƒ.bÏaÛà =ˆAV=pdIÌ"+ÖØ£-În‚ ã›`Ò‘Nm$•ŽòÈǽq_´ …P¿ûMiT£U¡GU²Oxl!£HI @„Žä¢%ßÄÉg1ò‘N"“H(&Jò”šÔ"*§åɺRl¬Ü¤,cK/ÚÒŠH\$(¡Êþár–¾\“0+IË@oÆœ¤2‹IÌK"3O"%÷¨ k^›ÙÔæ6¹yMßtœáç6¿9Nsf³œç g:ÕÙMv¶“œU€ç<­ùNzzSž÷Ô¦=õ ÏSlkšÔÔN? ª‚Ÿu§ZO†64<¨DÁiPˆZ´¡¥è8Ïèšm5!éHáPÈ,’¤)UéJ{ ²BÔ`„ØåLiZS›Þ§9Õ©xêC ¦1ØéP‰ZT£©IåŽKQñÓ ²À™,•êT©zËžBÕ©OÍ@T«ÚU¯®@LªÔ±~­iõ*€®ºU²" ¬Z݆è*€ þеvõ^ÀWøµ~­ë_ë Ø –ƒeb= X¼î€¯…E¬dûZØ».ö±‡cÕÚÙ†‰Õ­o+VûÚØË.öœE­fy ZÌš–µ› ìlc[ZÂÂÖ¶‰l 8ëZÓê5²š ®o=ÛU¶šÔ -\ÍêÖÜ·¶§Ímbqû×Ô>—¶Índk×àÆv¸ÔÅmw^áþ¶ºÅílX¥ùRßÀ¾Ì ê\a«XËV7³•åîc+^Ûö÷¾×®ËßþÊ–µÞm-o›_À:¸•]­€KkÞ §W½i=®öªáÖøÂ·¹sµ/zÁ‹`ì~wº²U°…¡ûÜcþ–¿$Nqc¬Zà ÖÄúpŒuÌ[Ë~wÄçp†¿ÊÞQ¾´ ޝYé»_¼¢øÁ4~2†¼âSÙº%&°~§µƒÉ,ë6ƒö”¶t—°m›lÛÛÖ·±ÚêmþÝéÖH¤=:… pUÝñ–÷36œHi¼ÛÖóÖ÷¾™ˆmsg…Ð ·ž‘mj"ZÐùD¸½¬ðÍ:ÜÏ`ø^'¾e~w²Ü-8– îèD›ºÕ//ÈÏÜi% ¼äÿ3·ýÐ[Q§< 7»£ƒïQG|!_ùËsîc yÏ®Á½p#š2Ow½ï1 ›ã¸v¬®{õ_ÿÂÂݯ֥\e¬ã¸ÀTwv®­žà°—Ü»`÷4°+¼õª÷šë„u{¦}waS²Ñn0Ÿ/þLkœî¥Žî¦Wíc¼ŸøÕv¿9zUgü²ZÆ{9Ÿ_Þ=§Ó­ÆüšK­sðÖyÇþ:MÞ÷teœM–r£5¿úÅ[·ñ¡ÏtìOw¾Ÿ}¼W^4´Uþx¢_øòއ:ëo‹{Ï:ñÌvtã%_zÓ¶½ ¼tâ‘_û‡YíÌ—ñC_ø÷9ʆu MòËSô˜NyåÏ ä»¼û ~~¤P¿ƒK˟д'~§ Ÿ~Ò¿>Ö¸¯ú´¯ùvoòêËüþOû2oåü¯õ´,¼oÖæï•þ.õ6ب¯Ç:ðÙ|­ü<ìÞîÆmøà›Ø‚ÍÅØ¯µ«]ðÊÎÉH°¾ô.WÐí lî>0Ù‚ìÿ,pêOέ”N…@æç’pH0ÐþòÍþ㜠…é^ÂæªP ·°“ °¥ Ã0 ¯Ðé€@†@Ž éTâH Û5hÎ#²ðsø` È ï1ȰÃÌÐ?¦( êsðP÷Awè\*vÐ}1s’æ|4ègjh|$q`^¨ˆh q' Q õðÞøs2QmÔe¶FzÞÆ÷Æ~hõgÅ;ѰÝM£Ç€fˆÄ‡s ‘ ÉY¬Çˆ~Qy€1kÑ A1¹r±v1+Ñ€~&€ª'lŠˆˆàènf‘™ñÝ+ÛúpëhMQ‡zÊñ€ÀÇ~¢æyq¿1  «i¨5þÑ7jüñ‚†‘ -Q™Åõ§ò‡èqÃQúî‘™ "¨&’!Ñå#,ò";R#=R$Õ+#ãG%Á*ÄŠbê@ â2‚NâT l2&SR'Kr¹>ŒÉ²bØ!n2ê'E!h’&u’A2É”L¾d)Õ¡ŒRxa*©Òv +™Òy*£rŽ!`² ÎrB) ºa2ŒÁ&Oà ÐÒ+Áq%£ï½Âò'E€âÊ ¬)wa!Æà/—& sÚr(»ò.©,ùÒ%u„Ó á2áR.B0s(Ó Âþˆ"²'—¬2còBá/C2CS@S+ã7ó3b6QÓ'*ûò5M€Ó0×!7ÃA9m“,ƒ²45a^9Õ¡7}SÖT3,Gë%ϲ,ÿ. â¾Sز6%¡!ìr<"6M3:Ѭ“߀SÉú’ÖsªS ð“+«2'9>g./ìž28[³*õS)ô?·P>}Ò@B5;)“™"ÔB½¢AY3S|‘¹ÑC³æ†¾ä )ò‰ÊˆCç‘ço‘wQSôBKbB 4 H1›@}r”DŤ‰GG§AÔGù†KÈE€Ò1FS"CAÌþ@]‡G{¥TH¡èCç1çdžöQc£ñH;(9rI[aFçóI 2røÑFÕtM7åJRn@%=§D±qƇCM%Y†HKËTFiÃî@Ñ´FOçK­”sÆ´ZÞ4Ž\ÑC±mìDMq!i†„µy^±ƒ5PYr5ôPßTR³‘{qJ‹‘“UqtUÑJÁTUÃôJ«ÑOcÕS?RPí-¹ ÕA5jµQ¦ÑHiuUÈUùxPuVqJKK+‘Q]5WuT³“>ÿ‡vÔG²S/ñNáh“õGwÅM%Q‘Y…uXßÑ«Õ"šT,«dD™õëþõDýG!“•YG”"Ò^Gh²G{QeðU –V)FáU@TÒ4Tç.Z‚1ÒL!Cwµé:ÌW5Þ8–déáLudKVeGÄc±0dE5eWVfûM/_Öb5ÓN“(`&ýó(AAOâgÁ³>AAoòhûs$åU;ÒhŸ³‚6jý“:vjwV4û³:“Ö”r+±v ¸¶ OVd6?÷“6s³hÁÁ1³¶(ùók¯ö6ÑÖjá6n™@lm±eÎf›¶jÑ“8ý’1Óò”S<Û¶&§¶ær ˆ¶&Ó21÷0BnË2ÜrW-!×<¹Ò=u¶qþ-7q%7mI·=«V$Éfòt1ÓæVg‡¡m±r9ióuÓ!³<]u+÷-e— 6¡vm³sµR:/Ók1!6wpks3çö+÷d+ÖoÉR0Ÿ)›SkýòyNÓzq’.‰sq BmÕ¶g;Ázy¹w:Í~ßj—|éözç o­PbÛ É¨W8•Öy¡w0}¡4¥w je³8¿`3‡·tø~gw{W~3!r›÷8m×~Ø{’iÿ·¾¡}1X7)X{“S7 ¸{?óu1÷38n—}ww„Kx7§“y‡×9W„'wi÷·æú„á2:shâp8þp 7}¢=Å!ÎóxÉó=÷Ó(©ø®x|݉÷=¥ØqeŠÕÒ‹‹ ~øÍü÷AÏvA“6ÝvIU×bg–Ž×Mz U d£ö˜ûØÿY™ ¹ O@÷’F·ÁÙ‘’#Y’'™’¹aÒ[[s@ꘓåAŽýv“;Y”éíŽ{5¹;FY•i6‘…X“WR©bY–g™–kÙ–ká’kM‘ •‘oÙ—˜ƒY˜Õ‘'Ö7*Ò*t•—¹OÞ ™“9f™Yš[É eª Vòµ+´™ ¹ùLþ°UÒ0#¡ñ”N)¥ŽTâVÎu1:qc×ycçþ™]Õ¹OÓ¹’ªÙ§N²"•žé%Ú ù"ž/Ö ÿ°žÿ`œ‰­™.¨sXˆa`ýõKîÅ›veq£%`±¢ 6\1‘?:£O:OMtRå_E”Mu”Zñ´£ÕUX":D7†£·t–MYŒôù¬Ú_Ï¥SÿÙ~Ì1K+•r´•S“”Õ¥õO«ñYIô“Ú©›µU©'z­QzjÚ†|:|¢º©mUL¯´œÇñšGú¢Ú]úuQ2Ç¢»1KãQkfGåZEÕ«¥м¯‘Té4fÂYDµ9Xså ÇŸKQ°½¦^±\ïZ­8Í™5Üšþ ivÜ™X¡µN•Ÿz±±”§º²Ñ™µñ¨µZ©´´Û²«ôdÆ»KѺ¶½ùôtY³[¡µíPaÜù¨ùT·;©Û§›«»U[µ‹UÇÕ©Me¨W{JO{åWçžGû»ÁôXÓ±$ƒ›ätŒv(JUú­•ºE]š ¿' ‰ZkÚ&¯ïÕ·ÝÔ[G½Ú¶{zcD»†4ú¦5ñHszëÛ°ˆ›ñ”¿»[ÁW×úßš¢ Ï®³ùÃý€Zo[+:<#F|½ÙúùêX|\ü±=Æy¦¡÷yšo<R|ÃqœÇ[¤”ïÑ‘þ;ÄßÂÄ·ÔþžÉWÙY"QZ¬[|-tðž¨M“<)Ä»a%’Ê»Z\¡È‡4¾9›²ã»Ëí9ZwBãœH¡uÌ7Ò³;ô¶Aæ¼aÍ ¶Í×ùUÃzÈ16Ï™³ 1'¦SÂÒÁÁu„UÓ5ß­{וۮ7>É¿4ÔÔàÍ´Ïq‘­>¼%žâsÝX•1âûe¯Ó»âßß1Þ¯·½ï¼¨á]·è[¡ZãM[Jm½7=ä‡y¾äÇ}Î<ËÈŽþñTœ'Óí¨Ð‹úè÷4S‰[Ûpªš·Ã=¤›u¨9ÞaíËíI=Õ¹Äî1µÜ·›ºÂÓ\ç =Ë'‰Û• ­F%W^a´ßÕ{ܸ^^wò+Bßðþ-_ó—¤ð+ÆIÞú›Û{'@]įgÎÇ{êI¡]”V.¸U¼ÌôÊ>N[ÿF)ÚõAßË‹€EEÅYè…{ LÄ'¤ó•}vßã\¶™ß÷u¿öÝ<÷{ÿóc5õû´Ù ¥øÇ›Ëó=ŸìqÒ%ƽI'¼üùY"]ÀA}ýCšüSý¹Ö"×ðëÕt§Ú#}ý§ZK©Ì5ëÛaÝ„‘Ò^ßnßôÂ)ªy󸪢×&€¡`8*sÁCRÔb¥V?P­åð˜Òm×zzAƒ×&µ åŽ9ÙRKߪ:±-Ÿïö!:%5µç%ØÇ†þ§³öe7V‡ØÃ¸XÕ…5d„TÐYdgñ”i¢·è’(x¥åXi%ÙèF&CYØ–š‰;)– 'º«È{'ã‹;cL"Ù;wìÊ׊<ìSE•ƒ}ö-œÊu ŽØ|0Ф„ Bz §mø–MüMý:Ü6ý{o¾?õ¾DwJÙ!V»ôýØð95l¦It”è]®@/¶ ÷n"£<è6µûd]‘0UØb‰ê&Boýr ÙS ³™:µêÕ¨5žvÍ:¶ìÙ´kÛ¾;5X%íŠÍ <¸ðذ‡?Ž<¹òå¬Aý›¹ôéÔ«[¿Ž=»õÝìÆ+­=¼øñäË›?/Û¹§%£ãfc9ëyÏ|¶êŒY5¡öyЄ.´&ìÜÄtW æê†TêÔ¯¾­y&Œèlæ’þÙ¼yv®#Ú×HƒZnZå²&-Õƒ–õ¬«žV -DÕv‹Îê§©šiÓÆÔÓìSjç°×êõí÷ÖÁÖµLa}57XEþ>Žè >oûÄò„…‡#Úf9»Cf[[--VÚz§aMâq¿Ó×~³œÁœ3sµNÛm1 ÇF¦9BMŸ©ǰZ·#cñh¿Zn$j¶¬§ä³²Ã2¿|{YÞ%3K5\¸ +›!®ˆc&HóS¸þ9µœq‘7ÔT1 ¬òØò/Þðˆxl¯UòAÄ•!0Ì<M¥”zÀ¿Þ˜LQìbæ¦z«¡ÌSÌ+Ér•><ÞÌv9f{æó¤AóÄJ•¾™õ2´V,n“Øe)¾«ã7¾Kÿøîe¡G=¤4¿Àoc¸¶›±s› ïžMêµ]yÚuþ…  ß*¼¸ÕÓœXK¹Ð“I`…Wˆ…V8…²%![h€˜Y(†~xd^ˆ†i%k¶âà†oø†0È—†uh‡.†e‘p‡rH‡wˆ¨†?ņmȇà‡(ˆ‹Èˆ“‡¨wˆs„H‰•xh„ˆgÀ‡‰¨ˆ–艞èR{膜؉ŸhŠŒhRš8Š’8‰§èŠ‹xU{HŠ¥øŠµˆ†je³H‹¶È‹.øˆð ‹I0ÃHŒÅhŒÇˆŒÉ¨ŒËÈŒÍèŒÏÑ(ÓHÕh׈٨ÛÈÝèÔˆ‰Šév¬hwßhŽçˆŽé¨ŽëÈŽíèŽïñHŒåÅF` pùˆû¨ýÈÿè )Ii ‰ © Éé ‘)‘I‘i‘‰‘©‘ygõÈ‘!é‘#)’%I’'i’)‰’+©’-É’/é’1éõ 5Ù6‰“7©“9É“;é“= ”?)”AI”Ci”E‰”G©”IÉ”Ké”M •O)•QI•Si•U‰•Ry•[™•]É•_é•a –c)–eI–gi–i‰–k–jé–l —o)—qI—si—u‰—w©—V;exmh-2.9.0/lib/html/bugfixes.html0000644000170700017070000000623713201227060016232 0ustar valdisvaldis Exmh Bug Fixes

Bugs fixed in exmh since 2.0.3

  • You can now have more than one exmh running on the same display
  • Fixed MIME formatting in Receipt-Notification message
  • Fixed encoding of whitespace in header lines
  • Restored 'Invoke menu with right button' message on large messages
  • Unseen sequence is no longer trashed after a sort or pack
  • Fixed ordering of MIME type guessing; It used to be mailcap, mime.types, magic, now it is mime.types, mailcap, magic
  • Fixed mailcap file extension parsing to ignore entries with nametemplate=%s
  • Fixed problem in X-Image-URL with ~ in pathnames
  • Fixed bug in alias editor
  • Fixed address-book lookup/expansion to create a new "To:", "cc:" or whatever line so wrapping isn't a problem
  • Improved code for posting to newsgroups
  • Consistent field width for the count in the Unseen window
  • Fixed installation glitch where hitting Verify before Patch would raise an error about an undefined variable
  • Added a file create of .mh_sequences to the New Folder code
  • Fixed small bug in searching body of message
  • Fixed bug with compose in empty drafts folder
  • Fixed a minor bug in the regular expression for URLs, so <mailto:foo> loses the trailing '>' as it should
  • Fixed handling of extra parameters on mailto: URLs
  • Don't display message parts if 1) it's a text/*vcard; or 2) it's got a Content-Disposition: Ancillary header
  • Fixed error in regexps in ftoc.tcl where digits followed by a "+" would confuse the marking of current message
  • Fixed Help...>Color Legend crash
  • Made menubuttons and regular buttons the same size when using tkstep
  • Fixed the actions for Rescan, Pack, and the various Sorts not to call Msg_ShowSomething afterwards. This had the unintended side-effect of, if no current message was set, setting the current message to the first unseen message
  • Closing html window during install before the page is fully rendered no longer crashes
  • If there's a PGP error while processing the message, show the message raw
  • Eliminated extra newline in editnow window
  • Sped up startup time by not pre-caching nicknames for all the folders
  • Sedit was not inserting Mime-version header when it should have
  • Allow ispell preferences to work before sedit has been opened
  • Fixed problems with annotation settings
  • References to exmh(background) should have been to exmh(bgPeriod) in BackgroundFixup
  • Fixed <a HREF="file.html#location"> in HTML browser
  • Prompt the user before executing the command portion of a button tag which is either non-local or in /tmp
exmh-2.9.0/lib/html/AddressBk.html0000644000170700017070000001353113201227060016253 0ustar valdisvaldis Address Database Help

Address Database Help

The Address Database is provided to help you automatically track names and email addresses and to perform lookups of partial names and addresses.

Storing data in the Address Database

You can choose to make the address database self-maintaining or you can maintain it "by hand".

For a self-maintaining address database, set "Enable Address Saving" to "on" in the Address Database Preference panel. As you view mail messages the "From" address will be automatically extracted and a corresponding Address Database entry either created or updated.

You may also want to enable automatic deletion of old addresses. Each address in the database is marked with the date of the last message from that address. You can set a "Remove Old Entries" to "on" and set "Days until removal" to the maximum elapsed days from the last message from an address and your address database will be "self cleaning". Note that settings related to "Remove Old Entries" will be ignored if "Enable Address Saving" is not "on".

For a "hand maintained" address database, set "Enable Address Saving" to "off". When you are viewing a message with a sender whose address you wish to keep, press the key defined in the "Key to save an address" field (default is Ctrl-Tab).

Use of LDAP servers

You can also use addresses stored in an LDAP server.

You will need to have openldap installed on your system. Enabling LDAP requires that you add LDAP_Lookup to the "Expand Methods to use" field in the Address Database Preferences window. You will also need to provide the name of the LDAP server and the root for your LDAP search.

Address Expansion: using data from the Address Database

Note: Address expansion is only supported in the exmh Simple Editor (Sedit).

The Address Database can be used to help you address email by using the Sedit "<addrexpand>" key. That key defaults to Control-Tab but may be changed using the Binding.../Simple Edit menu item of the main exmh window.

Address expansion by Address Database lookup is performed by typing a partial name or address in your message (on the "To:", "cc:", "bcc:", or "dcc:" line) and pressing the "<addrexpand>" key. You can expand multiple names, one at a time, by typing a comma followed by another partial name or address and pressing the "<addrexpand>" key again.

The Address Database Browser

You can browse and edit your Address Database using the somewhat misnamed Address DB Browser. This is accessed from the Address.../Address Book menu item of the main exmh window.

Fine tuning your Address Database

  • People with multiple addresses

    The Address Database does not attempt to recognize that one person can have multiple email addresses or email address variations. Each different address string is treated as a separate entity.

    You can streamline lookup of people who send you mail from multiple addresses by using the "exclude" facility of the Address DB Browser. Select the address you normally use to send mail to the person and mark all other addresses as excluded. Do not delete the addresses you don't normally use for sending as they will just be added back in the next time you receive mail from that address.

  • Filtering

    You may want to prevent mail from certain names such as "root" or mail stored in certain folders such as high-volume mailing lists from automatically causing updates to the Address Database. All email addresses listed as "Alternate-Mailboxes:" in your .mh_profile will be automatically ignored.

    Filtering is controlled from the Address Database Preferences panel. If the "From" address for a particular message is not being updated due to your preference settings you can still force it to be stored by pressing the key defined in the "Key to save an address" preference setting. The default setting is Control-Tab.

Idiosyncrasies and limitations of the Address Database

  • The Address Database does not support lists of addresses, one entry can only contain one email address, you should use MH Aliases for lists of addresses.

  • The Address Database only supports expansion of partial addresses on email address lines of a message (i.e., the "To:", "cc:", "bcc:", "dcc:", "Redistribute-to", "Redistribute-cc" lines). Address expansion cannot be performed on continuation lines.

    If you have set Sedit to break lines while typing and enter more than one address for expansion the line may be broken by Sedit. In this situation it will be necessary for you to temporarily turn off line breaking and join any continuation lines.

  • The Address Database maintains a pointer to the last mail message received for each entry. This pointer is only valid if you have not packed, moved, or deleted the message as it is only changed when you view a message.

  • Address database entries in the browser are initially sorted in alphabetical order by the text name and then by the email address.

    However new entries are not sorted as they are added to the Address DB Browser. You will find new entries at the end rather than in their proper place in the alphabet. You may resort the list presented in the browser at any time using the Database.../Sort menu item.

Origins of the Address Database

The exmh Address Database code was originally written by Berry Kercheval and was inspired by BBDB, the Insidious Big Brother Database, an Emacs add-in.

Addresses and Aliases

Main Help Index

exmh-2.9.0/lib/html/PGP.html0000644000170700017070000000552213201227060015040 0ustar valdisvaldis PGP

PGP

The Pretty Good Privacy package from Zimmermann.

PGP lets you sign and encrypt messages using public keys. There is considerable documentation that comes with PGP itself. PGP is to an email message what an envelope is to a letter.

Exmh allows to conveniently use PGP to encrypt or sign your messages and decrypt and check signatures on messages you receive.

To start using PGP, you have to create a key pair. A key pair consists of a public key (that you want to spread around) and a private key (that you don't want anybody else than yourself to have).

The private key is protected by a password. You should be *very* careful not to lose that password *and* not to let anybody get access to it. PGP can offer a very high level of security, but if people can read your file (especially the file that contains the private key) and can find your password (reading keystrokes is very easy once you have access to the Xserver) then all the great work put into the encryption algorithm is totally useless :-)

This button will run PGP to create a key pair. It will create a directory where PGP keys will be kept (by default ~/.pgp), make a key pair (this can be fairly time consuming), sign the key (you should read the PGP documentation to find out why this is done. It doesn't explain why it isn't automatically done by PGP, though :-( ) and finally will send the public key to the keyserver so that other people can find it (in case they want to send you encrypted mail or if they want to check some signature of yours).

You must restart exmh after creating your public key. By default, exmh does not display any PGP-related menus if you are not yet set up for PGP.

Supported PGP program versions

Currently exmh has support for PGP versions 2.6, 5.0, 6.5, and GnuPG.

You can use all versions separately or simultaneous from within exmh. You need not have all versions installed to use exmh PGP support.

Having both PGP versions 2.6 and 5.0 on one system can lead to problems, because the main binary of PGP 5.0 is called pgp like the 2.6 one. The pgpe, pgps and pgpv commands are links on that binary. Because calling the pgp binary of 5.0 itself does nothing but print out a version usage summary, one way to disable it, is to put it into a location that is not in PATH and edit the symlinks pgps, pgpe, pgpv to point to this new location. PGP 2.6 and 5.0 can peacefully coexist on the system this way and be used both from within exmh.

Currently, the PGP 6.5 support wants the 'pgp' binary to be called 'pgp6' (rather than the default 'pgp'). PGP 6.5 can co-exist with both 2.6 and 5.0 if this is done.

Main Help Index

exmh-2.9.0/lib/html/Y2K.html0000644000170700017070000000110013201227060015003 0ustar valdisvaldis Exmh and Year 2000 Issues

Exmh and Year 2000 Issues

Exmh is a user interface implemented as a Tcl/Tk script. It uses the MH (or nmh) package for many basic mail handling tasks.

Tcl/Tk version 8.0 is Y2K compliant.

MH and nmh are also Y2K compliant, storing the year as 4 digits everywhere.

I anticipate no Y2000 problems for exmh.

Brent Welch exmh-2.9.0/lib/html/Seditpref.html0000644000170700017070000000233013201227060016331 0ustar valdisvaldis Sedit Binding Editor Help

Sedit Key Binding Setup

Use to change the keybindings for edit functions.

Options

Type Kills SEL - whether or not typing overwrites the current selection.

Paste Sets Insert - whether or not <Button-2> to paste also sets the insert cursor (where stuff will get pasted).

Note: The selpaste function is for additional keybindings for paste.

Scroll Button: The Tk text widgets scroll if you hold down a mouse button and drag. This setting chooses which button to use. The default is <Button-2>. In this case, if you drag scroll, there is no paste operation.

Event Syntax

  • Any sequence like <meta-x> also results in a binding for <escape><x>
  • Case is significant in the keywords Control, Meta, Shift, Key, etc. Watch out for BackSpace, with a cap S.
  • Multiple bindings: to bind multiple (different) keystrokes to a function, separate the sequences with spaces.

The Events Helper lets you discover what events are generated by the keys on your keyboard. exmh-2.9.0/lib/html/left-arrow.gif0000644000170700017070000000026713201227060016276 0ustar valdisvaldisGIF87a$ò¤¤¤PPPxxxÄÄÄÓÓÓ,$„XºÜþPÀIã8ëÍ»VÂåäW„e:‚b¨ëÙnÀ w¬KØ÷–Ó„]mH,3¿ Èl:ƒÁ@@å%˧–V‘2åvLèRÖ°˜ü41W,ÛéFƒQ@¡q„«<=w35‚>‡q‡1xŽ%‘,R—˜™š›™ gŸ ¡¢£ ;exmh-2.9.0/lib/html/Import.html0000644000170700017070000000057213201227060015664 0ustar valdisvaldis Import Mailboxes

Importing Mailbox files

Exmh uses the MH inc program to extract messages from mailbox-format files. It does not know about all formats. It assumes the directory you name contains one or more mailbox files. Below is a log of the inc output.


exmh-2.9.0/lib/html/newfeatures.html0000644000170700017070000000372613201227060016746 0ustar valdisvaldis Exmh New Features

New features in exmh since 2.0.3

exmh-2.9.0/lib/html/index.html.old0000644000170700017070000000731713201227060016302 0ustar valdisvaldis Exmh 2.8.0 Manual

Exmh 2.8.0

2.8.0 released April 28, 2012

exmh-2.8.0.tar.gz

Thanks to Jerry Peek for putting "MH & xmh" up on the web. This is the MH bible!

If you are using exmh now, read this Quick Intro to get started right away.

General Documentation

Context Specific Help

More Documentation

exmh-2.9.0/lib/html/Sedit.html0000644000170700017070000001157613201227060015470 0ustar valdisvaldis Sedit Help

Sedit

Sedit is a simple editor built into exmh. The editor works on draft messages that are kept in your MH draft folder. When you do Compose, Reply, or Forward, a new draft is created for you.

You can customize the key bindings for this editor.

Here is what the buttons do:

Abort - remove the draft message from the drafts folder. The editor window is removed.

Save&Quit - saves the message in the draft folder but does not send it.

Help - displays this window.

Quote... - Bring up a menu with the following options (replies only):

    Quote - Insert a copy of the current message. See the Quote preferences for information about customizing the copy of the message.

    Quote MIME - Attach a copy of the current message as a part into a multipart MIME message.

Send - saves and posts the message. By default it is removed from the draft folder when you do this, unless you select Keep on Send.

Sign - append your .signature file to the message. If you have autoSign set, or multiple files match .signature* then this button is replaced with the following menu.

Sign... - Select the signature file for the message. It is added when you select it, or when you Send the message if you have the autoSign Preferences item enabled. In this case, if you select the intelligent option, one of the signature files specified under the Intelligent Signatures Preferences option is used, depending upon the destination of the message.

Text... - apply text/enriched formatting to the current selection.

Crypt... - Options for encrypting and/or signing your message. Use format to specify email encoding (plain, application/pgp or MIME multipart). The version submenu controls the application used. The sign submenu selects the signing method or if we should sign AND encrypt. The encrypt checkbox indicates if the message is to be encrypted for the recipients (where an Fcc: header automatically makes the author a recipient). If the author has more than one private key the "Choose Key" option allows for the key selection. Finally, for those that cache their passphrases the "Clear Passphrase(s)" allows for clearing the cache.

More... - Bring up a menu with the following options:

    Keep on Send - if this button is highlighted, then Send will not remove the editor window and the draft will remain in the drafts folder after you send it.

    Format mail - this breaks long lines (> 79 characters) at word boundaries.

    Attempt mhbuild - run the message body through mhbuild before sending. If you know the # directives of mhbuild, you can use this quick hack to compose MIME messages.

    Quoted Printable Text - make the content transfer encoding of regular text messages quoted printable to protect 8-bit characters.

    Ask for Receipt - Add a Disposition-notification-to header to the mail. This will request a receipt to the address in the header field.

    Attachment... - Bring up a sub-menu with the following options:

      Attach File... - Attach a file as a part into a multipart MIME message.

      Attach Message... - Attach a message as a part into a multipart MIME message.

      Attach Reference... - Attach a message/external-body part as a reference to a FTP file or a local file.

      Insert File... - Insert a file directly into the message.

    Whom - displays the list of recipients for the message.

    Spell... - run your spell program over the message body. Select this with the spell preferences for the Simple Editor.

    Find SEL - search the message body for the selected string.

    Save Buffer - write out the editor buffer to disk. This is only for paranoid folks. The Save&Quit button or Keep on Send options actually result in the draft remaining. This Save button just writes the buffer to disk but does not change the default behavior of renaming drafts after you send them.

    Run mhbuild now - Pre-process the message with the mhbuild program and put the results into the editor buffer.

    Mime Preview - Display the message as it will be seen by an exmh user.

    Alternate Editor - switch to using your alternate editor.

Filter - The Unix filter mechanism provides an entry widget where you can specify an arbitrary Unix command line. Once specified, selecting a region of text and hitting "Filter" has the effect of sending the selected text through the filter, and replacing it with whatever the filter produced. An "Undo" mechanism is provided in the event that the filter does not have the desired effect. Moreover, each unique filter you execute is stored in a history mechanism, accessible via the "History" menu adjacent to the text entry field.

Main Help Index

exmh-2.9.0/lib/html/exmh.README.html0000644000170700017070000006010513370472452016323 0ustar valdisvaldis exmh README

exmh.README.html

Contents


Version

Last modified: Wed Nov 7 00:15:17 EST 2018
exmh version: 2.9.0
"Brent Welch" <welch@acm.org>

exmh is a TCL/TK based interface to the MH mail system.

Version 2.8 requires Tcl/Tk 8.3 or higher. exmh is known to work with nmh versions 1.3 and higher, which is available at http://www.nongnu.org/nmh

Experienced EXMH installers should check FLASHES below and the exmh.CHANGES file.


New EXMH installers

Please read through all of this, thanks, especially the part at the end about the TK send command. See also the on-line FAQ file under the Help... menu.

The exmh documentation is now all in HTML and viewable from within exmh.

Please encourage your exmh users to REGISTER via the Register menu entry under the Help... menu. This lets me track exmh usage and get user feedback. I won't abuse this registration - there is no obligation associated with registration, but I would like all exmh users to do it.

All registration does is send me a mail message. You get to add your comments, pro and con, about exmh. I've learned a lot from the 2000+ registrations I have received so far. Thanks!


Other software you'll need

EXMH lives "high in the food chain". You'll need some additional software. Please review the necessary and optional packages for exmh.

Known Bugs

See the exmh.BUGS and exmh.TODO files in the distribution, or the Exmh SourceForge site.

Exmh Wiki

See the exmh wiki for a web site you can use to share tips and tricks with other users.

Frequently Asked Questions

See the exmh-faq.html for answers to some frequently asked questions. This information is now available via the FAQ button in exmh.

Flashes

  • 2.8.0 A tarball release after many, many years. Lots of good stuff has accumulated in the CVS source base. You'll need to troll through the exmh.CHANGES file for a record. Many thanks to the CVS committers.
  • 2.7.2 More bug fixes, plus some performance improvements for the new sequences code added in 2.6. The exmh-strip utility is integrated as "Save/Extract Attachments".
  • 2.7.1 (Wasn't officially released in tarball form.)
  • 2.7.0 Accumulates over a year of minor fixes in the CVS tree.
  • 2.6.3 Fixed awful pauses caused by sequence searching in the front end. Fixed inc-on-startup.
  • 2.6.2 Fixed Flist button, some optimizations to sequence handling.
  • 2.6.1 Various fixes, but the Flist button is broken.
  • 2.6 adds generalized sequence handling and fixes various bugs.
  • 2.5 adds color highlighting for in-lined replies. Fixes a bug with "Keep on Send" in 2.4.
  • 2.4 accumulates bug fixes and some code cleanup.
  • 2.3.1 fixed an installation bug in 2.3 that showed up when you installed without the .exmhinstall cache file.
  • 2.3 captures 6 months of feature tweaks and bug fixes by the hard working exmh-workers crew. The CVS sources are now at SourceForge.
  • 2.1 and 2.2 were made while Brent was at Scriptics/Ajuba.
  • 2.0.3 is done as Brent finally moves the sources into net CVS and asks for help maintaining the code. For more info on CVS, see http://www.scriptics.com/software/netcvs.html
  • 2.0.2 is done as Brent leaves Sun for Scriptics Corp, http://www.scriptics.com/. I've tried to shift all email contact to <welch@acm.org>, and am housing exmh at http://www.beedub.com/exmh/.
  • 2.0.1 fixes a bug in mime.tcl that prevents temp files from being deleted.
  • 2.0 is finally released. This collects a host of minor bug fixes, most notably to ispell and the address book.
  • 2.0zeta fixes the exmh-netscape interaction that was added in 2.0epsilon.
  • 2.0epsilon features cleanup of the address book, the ispell interface, and the intelligent signature features.
  • 2.0delta is a collection of fixes and features.
  • 2.0gamma is more bug fixes, especially in the new HTML code. There is also a new Quote package that computes a cleaned up version of the message to which you are replying.
  • 2.0beta has many bug fixes for the alpha release. The new line-breaking behavior of the built-in editor has been made optional, with the old line-breaking behavior as the default.
  • 2.3.1 fixed an installation bug in 2.3 that showed up when you installed without the .exmhinstall cache file.
  • 2.3 captures 6 months of feature tweaks and bug fixes by the hard working exmh-workers crew. The CVS sources are now at SourceForge.
  • 2.1 and 2.2 were made while Brent was at Scriptics/Ajuba.
  • 2.0.3 is done as Brent finally moves the sources into net CVS and asks for help maintaining the code. For more info on CVS, see http://www.scriptics.com/software/netcvs.html
  • 2.0.2 is done as Brent leaves Sun for Scriptics Corp, http://www.scriptics.com/. I've tried to shift all email contact to <welch@acm.org>, and am housing exmh at http://www.beedub.com/exmh/.
  • 2.0.1 fixes a bug in mime.tcl that prevents temp files from being deleted.
  • 2.0 is finally released. This collects a host of minor bug fixes, most notably to ispell and the address book.
  • 2.0zeta fixes the exmh-netscape interaction that was added in 2.0epsilon.
  • 2.0epsilon features cleanup of the address book, the ispell interface, and the intelligent signature features.
  • 2.0delta is a collection of fixes and features.
  • 2.0gamma is more bug fixes, especially in the new HTML code. There is also a new Quote package that computes a cleaned up version of the message to which you are replying.
  • 2.0beta has many bug fixes for the alpha release. The new line-breaking behavior of the built-in editor has been made optional, with the old line-breaking behavior as the default.
  • 2.0alpha folds in many user contributed features and an HTML viewer for documentation. This version requires Tk 4.1 for socket support and some other features. There is a new Top Ten List in preferences that consolidates the most important preference settings into one place.
  • 1.6.9 fixes to font selector and sedit formatting.
  • 1.6.8 is more bug fixes. Cut and paste finally fixed? Font selector added.
  • 1.6.7 is more bug fixes. Most notable is fixing up of the Paste operation in the editor.
  • 1.6.6 is a collection of bug fixes and minor improvements. The next big release will be a 1.7/or/2.0alpha that rips out support for Tk 3.6 and folds in various contributions. There may still also be a 1.6.7 to fix bugs in 1.6.6
  • 1.6.5 includes an overhaul of the Flist module that highlights folders with unseen messages, and counts unseen messages in total. This also detects 8-bit characters in all cases within Sedit. CLIPBOARD support for OpenWindows users (Tk 4.* only) TMPDIR and EXMHTMPDIR environment variables honored to map /tmp
  • 1.6.4 has fixes for the bugs in 1.6.3
  • 1.6.3 collects many minor enhancements, plus integrated ispell support for Sedit, and new faces code from John LoVerso. Check out the new "Faces Row" option to display all matching faces.
  • 1.6.2 collects several minor enhancements
  • 1.6.1 fixes two minor bugs and adds support for Sun Attachments.
  • 1.6 released as Brent moves from PARC to Sun Labs. Exmh lives. This release is stable with Tk 3.6 and Tk 4.0b3. The FTP site and WWW Page will migrate to Sun shortly, although parcftp will continue to host exmh for a while. Update your bug mail address ("maintainer") to Welch@acm.org

Multidrop+Inc style inc has been added. Set up your .xmhcheck file to use the MyIncTmp folder. Any messages in that folder get sorted by slocal.

The man page has been chopped into 4 documents:
exmh.l - a tutorial
exmh-use.l - a more comprehensive user guide
exmh-custom.l - a guide to exmh customization
exmh-ref.l - a terse description of all buttons and menu entries.


Performance Hints

Grab the Tcl/Tk 8.0 releases for a nice performance boost!

Squeeze the last drop out of message display by disabling the separator bars in message display. (Show Graphic Part Separator under MIME)

Really large folders make exmh run slowly. Take this as a hint to reorganize things into sub-folders if you have more than 500 or so messages in a folder.

Bound the unseen folder search by defining the .mh_profile

	Folder-Unseen: pattern pattern pattern
entry to name the folders to search under. The default is *, so all folders are searched.

Reverse Video

It takes just a few resource settings in your ~/.exmh/exmh-defaults-mono file to get reverse video on a black and white display:
! For widgets
*Background: black
*Foreground: white
! For highlights
*c_background: black
*c_foreground: white

Colorized Headers

Did you know you can colorize rfc822 headers in the message display by setting *m_tagnames and related X resources? This feature has been around for some time, but seems to be little-known. Here's what I have in my ~/.exmh/exmh-defaults-color file.
*m_tagnames:    hidden subject from x-filters-matched content-type x-mailer repl
ied replied-to
*m_hidden:      -font 6x10
*m_subject:     -foreground blue
*m_x-filters-matched:   -foreground "medium sea green"
*m_content-type:        -foreground "medium sea green"
*m_x-mailer:    -foreground "medium sea green"
*m_from:        -foreground blue
*m_replied:     -foreground "violet red"
The *c_ family of resources has expanded a bit to allow control of both foreground and background colors for current, unseen, moved, and delete messages.

Mailing Lists

There are now three exmh-related mailing lists. YOU ONLY NEED TO PICK ONE LIST. Send your subscription requests to:
	exmh-announce-request 	- to receive release notices 
	exmh-users-request 	- to get exmh-announce + user discussion 
	exmh-workers-request 	- to just get exmh hacker discussion 
The mailing lists have the following addresses, but please send your subscription requests to the -request aliases. If you use the menu entries under Help, they format the message automatically.
	exmh-users@redhat.com
	exmh-workers@redhat.com

Acknowledgments

Thanks go to Ed Oskiewicz for inspiring me with an initial version, which is much modified by now. Thanks also go to many beta testers that put up with buggy versions and suggested many features that are now part of exmh. Feature requests that come with code diffs to implement them are especially nice.

The following employers of mine deserve credit for letting me indulge in exmh hacking: Xerox/PARC, Mark Weiser and Doug Terry. Sun Microsystems Laboratories, John Ousterhout. Scriptics, The Tcl/Tk Platform Company, John Ousterhout.

Honorable mentions:

There are a lot of other folks that contributed code and patches. Without them, exmh wouldn't be what it is today.


Features

As well as providing the usual layer on top of MH commands, exmh has a number of other features:

MIME support! Displays richtext and enriched directly. Parses multipart messages. A popup menu under the right button can invoke external viewers (metamail) for things not directly supported. Built-in editor allows simple composition of text/enriched format and multipart messages (via Insert Part).

Color feedback in the scan listing so you can easily identify unseen messages (white background), the current message (raised display), deleted messages (strikeout), and moved messages (yellow background). Xresources control these color choices.

Monochrome displays highlight unseen messages with underline, current message in reverse video, deleted messages with strikeout, and moved messages with stippled background.

A folder display with one label per folder. Color highlights indicate the current folder (red), folders with unseen messages in them (blue), and the target folder for moves (yellow background). Nested folders are highlighted by a shadow box. A cache of recently visited folder buttons is also maintained. Monochrome highlights are reverse video for the current folder, bold box for folders with unseen messages, and stippled box for the target of move operations.

Clever scan caching. MH users know that scan is slow, so exmh tries hard to cache the current state of the folder to avoid scanning. Moves and deletes within exmh do not invalidate the cache, and background incs that add new messages are handled by merging them into the scan listing. The scan cache is compatible with xmh.

Facesaver bitmap display. If you have a facesaver database on your system, exmh displays the bitmap face of the person that sent the current message (or their organization). Otherwise, it just displays a boring EXMH logo.

Background inc. You can set exmh to run inc periodically, or just to periodically count up the messages in your mail spool file. (Depends on proper TK send functioning. See notes below.)

Various inc styles. Exmh knows about three styles of inc usage: Inc from your spool file to your inbox folder. Inc from your spool file or POP host to a set of dropboxes as specified by your ~/.xmhcheck file. Inc from your spool file directly into folders. exmh can run the MH filtering program (slocal) for you, or you can let an external agent presort mail into folders for you.

Searching over folder listing and message body.

A dialog-box interface to MH pick.

A simple editor with emacs-like bindings is provided by default. It has an interface that lets you tweak key bindings.

Editor interface. You can hook up exmh to TCL based-editors like mxedit quite easily. A script is also provided, exmh-async, for using terminal based editors like vi. The emacsclient.README file has hand-wavy instructions for using emacsclient to talk to an emacs server.

Glimpse interface. You can index all your mail with glimpse and search for messages by content. The search works across all folders and runs quite fast. The indexes are only about 10% of the space of your mail database.

User preferences. You can tune exmh through a dialog box. The settings are saved in an Xresource-style file named .exmh/exmh-defaults. You can also put font and color resource specifications in this file, plus there are a few random parameters not exposed via preferences.

User hacking support. A user library of TCL routines is supported. The main implementation is chopped up into many smallish modules. So, you can modify a copy of some module to put your favorite mail reader hack in without affecting others (or convincing me to put it into the main line). There are also a number of places where hook procedures are used so you can refine the behavior of things like composing a reply message. Details in the man page.


Installation

Installation is done via the exmh.install script. Invoke it as:
	wish -f exmh.install
This puts up a dialog box that lets you patch various file system specific pathnames and enable or disable features that your system cannot support (e.g., facesaver, sound). You can test out exmh via this dialog before installing it.

Upon startup, exmh.install looks around for .exmhinstall files from previous installations. It will ask you which one you want to use, unless there is already one in the current directory. You can also use the Conf button to look for config files. This lets you maintain a set of config files, .exmhinstall.* if you need this for multiple architectures, for example.

In the install dialog, the "Script Library" and the "Install lib directory" are usually the same place. The script library is the run-time value of the library directory, while the install lib directory is the install-time value. The Test button now automatically changes the run-time value to "./lib" in order to test before installing. So, the only reason for the distinction between install-time and run-time is for AFS environments where writable and read-only volumes might have different names.

Remember to choose a script library directory that exmh can take up all for itself. The install is *not* smart enough to make an exmh subdirectory in a common lib dir (e.g., /usr/local/lib).

WARNING: you need to specify an alternate location - the install is *not yet* smart enough to handle leaving the script library where you unpacked the tar file.

After you set things up in the dialog box, then hit some buttons:

  • Patch - to apply site-dependent patches to exmh. The configuration is saved into a .exmhinstall file.
  • TclIndex - to compute the auto-load library index.
  • Test - to run the patched script.
  • Verify - to see what the Install will do.
  • Install - to install exmh.
If the install fails to work gracefully on your system, let me know! One common error is to get a complaint about the procedure "Exmh" not being defined. This happens when the value of the script library is not correct.

Tk Send Problems

VERY IMPORTANT. PLEASE READ. SOURCE OF MANY PROBLEMS. READ THIS HERE :-)

exmh depends on the TK send facility for its background processing. With TK 3.3, send now uses Xauthority mechanisms by default, unless you compile TK with -DTK_NO_SECURITY. A manifestation of problems are that background processing doesn't work: new messages are not scanned into the current folder, the flag icon doesn't behave, and so on. Similarly, use of the exmh-async wrapper script also fails. If you cannot recompile wish, then the trick is to get your X server process started with the right incantation.

You can easily test send (and my installation process should have...) Just run wish, and type in the following command to it:

	send exmh {Exmh_Status "Hello world"}
Obviously, make sure exmh is running first.

If you get an error, you need to recompile the TK library, or learn how to start up the X server so it does the right Xauthentication stuff.

Here is one example, for SunOS openwindows. This is an excerpt from an .xserverrc file:

    if [ ! \( -d $HOME -a -w $HOME \) ]; then
      echo "Warning: Can't write X authority file" 1>&2 ;
      auth_args=""
    else
      authfname=$HOME/.xnews.`uname -n`$DISPLAY
      ${OPENWINHOME}/lib/mkcookie $authfname -auth magic-cookie
      auth_args="-auth $authfname"
    fi ;
    ${OPENWINHOME}/bin/xnews $auth_args $server_args $xnews_config_args ;;
The general picture of what's going on is this:
  • some program generates a magic cookie (arbitrary string) and writes this to a file.
  • The name of this file is passed to the X server
  • The X server writes an entry for the DISPLAY into your ~/.Xauthority file.
  • Xlib reads ~/.Xauthority when you create a window, and passes the cookie value back to the X server.
If you have the xauth program and your server doesn't like to be told about the intermediate file, then you can use xauth to write into the ~/.Xauthority file for you, and apparently the right thing will happen. If this sounds vague, it is. For precise details, do some experimentation or ask your local X guru. If you come up with particular solutions, feel free to post them to "comp.lang.tcl" so other folks with similar configurations can learn how to do the right thing as well.

See also "misc/Xauthority" for similar info.


Concluding Remarks

If you end up using exmh on a regular basis, also let me know! If I can tell my managers that there are N users of my mail reader, there is a greater chance I'll have time to hack up more tools in the future (and still get paid). There is a Register User menu entry under the Help... menu that you can use for this purpose. Encourage your users to do this if you are an administrator at a large site.

Finally, please take time to read the man page before asking too many questions. If exmh gets an internal error it will display a dialog box with a TCL trace back and a What Happened: area. You can type short note into that area, and then hit the "mail to" button in order to file a bug report. I'll consider feature requests, but basically I'd appreciate it if you'd code up your feature and send me some diffs or just the whole file that is affected. Many of the neat features in exmh were originally contributed by its users.


Author

-- "Brent Welch" <welch@acm.org>

exmh:The Right Tool for the Job exmh-2.9.0/lib/html/copyright.html0000644000170700017070000000310213201227060016412 0ustar valdisvaldis Exmh Copyright

Copyright

Copyright 1999-2001 Brent Welch. All rights reserved.
Copyright 1995-8 Sun Microsystems Laboratories All rights reserved.
Copyright 1995 Xerox Corporation All rights reserved.

License is granted to copy, to use, and to make and to use derivative
works for any purpose, provided that the copyright notice and this
license notice is included in all copies and any derivatives works and
in all  related documentation.  Xerox and Sun grant no other licenses
expressed or implied and the licensee acknowledges that Xerox and Sun
have no  liability for licensee's use or for any derivative works  made
by licensee. The Xerox and Sun names shall not be used in any
advertising or the like without their written permission.

This software is provided AS IS.
XEROX CORPORATION AND SUN MICROSYSTEMS DISCLAIM AND LICENSEE
AGREES THAT ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY LIABILITY FOR DAMAGES
RESULTING FROM THE SOFTWARE OR ITS USE IS EXPRESSLY DISCLAIMED, INCLUDING
CONSEQUENTIAL OR ANY OTHER INDIRECT DAMAGES, WHETHER ARISING IN CONTRACT, TORT
(INCLUDING NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION OR
SUN MICROSYSTEMS IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

Back to the exmh index

exmh-2.9.0/lib/hourglass.mask0000644000170700017070000000166013201227060015443 0ustar valdisvaldis#define hourglass_width 32 #define hourglass_height 32 #define hourglass_x_hot 16 #define hourglass_y_hot 15 static char hourglass_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0x58, 0x00, 0x00, 0x34, 0x58, 0x00, 0x00, 0x34, 0x58, 0x00, 0x00, 0x34, 0x98, 0x00, 0x00, 0x32, 0x98, 0x00, 0x00, 0x32, 0x98, 0x00, 0x00, 0x32, 0x18, 0x01, 0x00, 0x31, 0x18, 0xfd, 0x7e, 0x31, 0x18, 0xfa, 0xbf, 0x30, 0x18, 0xe4, 0x4f, 0x30, 0x18, 0xd8, 0x37, 0x30, 0x18, 0x20, 0x09, 0x30, 0x18, 0x40, 0x05, 0x30, 0x18, 0x20, 0x08, 0x30, 0x18, 0x18, 0x31, 0x30, 0x18, 0x04, 0x41, 0x30, 0x18, 0x02, 0x80, 0x30, 0x18, 0x01, 0x00, 0x31, 0x18, 0x01, 0x00, 0x31, 0x98, 0x00, 0x01, 0x32, 0x98, 0x00, 0x01, 0x32, 0x98, 0x80, 0x03, 0x32, 0x58, 0xc0, 0x07, 0x34, 0x58, 0xf0, 0x1f, 0x34, 0x58, 0xfe, 0xff, 0x34, 0xf8, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00}; exmh-2.9.0/lib/flagup.mask0000644000170700017070000000366713201227060014723 0ustar valdisvaldis#define icon-full_m.bm_width 48 #define icon-full_m.bm_height 48 #define icon-full_m.bm_x_hot 0 #define icon-full_m.bm_y_hot 0 static unsigned char icon-full_m.bm_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x01, 0x00, 0xfc, 0xff, 0x7f, 0xff, 0x19, 0x00, 0xfc, 0xff, 0x0f, 0xff, 0xfd, 0x00, 0xfe, 0xff, 0x03, 0xff, 0xfd, 0x01, 0xfe, 0xff, 0x61, 0xff, 0xf9, 0x00, 0xfe, 0xff, 0xf9, 0xff, 0xfd, 0x01, 0xfe, 0xff, 0xf8, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0xfc, 0xff, 0x33, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x01, 0x00, 0xfc, 0x3f, 0x20, 0xff, 0x01, 0x00, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x00, 0xf0, 0x0f, 0x70, 0xff, 0x1d, 0x00, 0xe0, 0x03, 0xf0, 0xff, 0x09, 0x00, 0x00, 0x00, 0x30, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; exmh-2.9.0/lib/env.tcl0000644000170700017070000000460613201227060014056 0ustar valdisvaldis# env.tcl # # Grab things from the environment # # Copyright (c) 199 Sun Microsystems # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Sun Microsystems # makes no warranty about the software, its performance or its conformity to # any specification. # Env_Init sets up: # MHCONTEXT to give exmh a private MH context file # USER to avoid dealing with LOGNAME # TMPDIR to allow retargeting /tmp # PATH to make sure the MH programs are on the path proc Env_Init {} { global env global exmh # Use an alternate context to avoid conflict with command line MH # This has to be the same as used by exmh so that private sequences work # right. set env(MHCONTEXT) .exmhcontext # Merge LOGNAME into USER so we only need to look for one later if {[catch {set env(USER)} user]} { if {[catch {set env(LOGNAME)} user]} { puts stderr "No USER or LOGNAME envar" set user "" } set env(USER) $user } # Init TMPDIR if {[info exists env(EXMHTMPDIR)]} { set exmh(tmpdir) $env(EXMHTMPDIR) } elseif {[info exist env(TMPDIR)]} { set exmh(tmpdir) $env(TMPDIR) } else { set exmh(tmpdir) /tmp/$env(USER) } # Make sure MH is on the path # At install time, we may not yet know the mh_path, # and are just setting up the TMPDIR global mh_path if {[info exist mh_path]} { set hit 0 foreach dir [split $env(PATH) :] { if {[string compare $dir $mh_path] == 0} { set hit 1 break } } if {! $hit} { set env(PATH) $mh_path:$env(PATH) } } } proc Env_Tmp {} { global exmh # Doing this every time we use the temp file directory ensures # no-one steals it without the user knowing it. # We only chmod the directory if it doesn't exist to avoid # the case where exmh is run under the root account and # chmods /tmp, /var/tmp, or /usr/tmp if {[catch { if {![file exists $exmh(tmpdir)]} { file mkdir $exmh(tmpdir) file attributes $exmh(tmpdir) -permissions 0700 } } err]} { puts $err catch {puts stderr "WARNING: exmh using unsafe /tmp directory"} Exmh_Status "WARNING: exmh using unsafe /tmp directory" warning set exmh(tmpdir) /tmp } return $exmh(tmpdir) } exmh-2.9.0/lib/base64.tcl0000644000170700017070000000456113201227060014352 0ustar valdisvaldis# Emit base64 encoding for a string set i 0 foreach char {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \ a b c d e f g h i j k l m n o p q r s t u v w x y z \ 0 1 2 3 4 5 6 7 8 9 + /} { set base64($char) $i set base64_en($i) $char incr i } proc Base64_Encode {string} { Base64_EncodeInit state old length set result [Base64_EncodeBlock $string state old length] append result [Base64_EncodeTail state old length] return $result } proc Base64_EncodeInit {stateVar oldVar lengthVar} { upvar 1 $stateVar state upvar 1 $oldVar old upvar 1 $lengthVar length set state 0 set length 0 if {[info exists old]} { unset old } } proc Base64_EncodeBlock {string stateVar oldVar lengthVar} { global base64_en upvar 1 $stateVar state upvar 1 $oldVar old upvar 1 $lengthVar length set result {} foreach {c} [split $string {}] { scan $c %c x switch [incr state] { 1 { append result $base64_en([expr {($x >>2) & 0x3F}]) } 2 { append result $base64_en([expr {(($old << 4) & 0x30) | (($x >> 4) & 0xF)}]) } 3 { append result $base64_en([expr {(($old << 2) & 0x3C) | (($x >> 6) & 0x3)}]) append result $base64_en([expr {($x & 0x3F)}]) incr length set state 0 } } set old $x incr length if {$length >= 72} { append result \n set length 0 } } return $result } proc Base64_EncodeTail {stateVar oldVar lengthVar} { global base64_en upvar 1 $stateVar state upvar 1 $oldVar old upvar 1 $lengthVar length set result "" switch $state { 0 { # OK } 1 { append result $base64_en([expr {(($old << 4) & 0x30)}])== } 2 { append result $base64_en([expr {(($old << 2) & 0x3C)}])= } } return $result } proc Base64_Decode {string} { global base64 set output {} set group 0 set pad 0 set j 18 foreach char [split $string {}] { if {[string compare $char "\n"] == 0} { continue } if [string compare $char "="] { set bits $base64($char) set group [expr {$group | ($bits << $j)}] } else { incr pad } if {[incr j -6] < 0} { set i [scan [format %06x $group] %2x%2x%2x a b c] switch $pad { 2 { append output [format %c $a] } 1 { append output [format %c%c $a $b] } 0 { append output [format %c%c%c $a $b $c] } } set group 0 set j 18 } } return $output } exmh-2.9.0/lib/addr.tcl0000644000170700017070000013240613201227060014200 0ustar valdisvaldis############################################################################ # # Insidious Mail DB # #------------------- # Copyright 1996, Xerox Corporation. All Rights Reserved. # License is granted to copy, to use, and to make and to use derivative works for # research and evaluation purposes, provided that the copyright notice and # this license notice is included in all copies and any derivatives works and in # all related documentation. Xerox grants no other licenses expressed or # implied and the licensee acknowleges that Xerox have no liability for # licensee's use or for any derivative works made by licensee. The Xerox # names shall not be used in any advertising or the like without their written # permission. # This software is provided AS IS. # XEROX CORPORATION DISCLAIMS AND LICENSEE # AGREES THAT ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY LIABILITY FOR DAMAGES # RESULTING FROM THE SOFTWARE OR ITS USE IS EXPRESSLY DISCLAIMED, INCLUDING # CONSEQUENTIAL OR ANY OTHER INDIRECT DAMAGES, WHETHER ARISING IN CONTRACT, TORT # (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION # IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. #--------- # This package saves the e-mail address of everyone you get mail from, and lets # you send mail back with only a partial address. # # When you type part of an address in the To: or Cc: field, Ctrl-TAB will # attempt to complete the address. # # The concept owes a lot to the Gnu Emacs package "BBDB" by Jamie Zawinski # (jwz@netscape.com) but this implementation is strictly my own. Thanks, Jamie! # # # A neat feature of the browser (and entry editor) is that you can pop up (a la Clip) # the last message you got from that person. Be careful, though; if that message was # deleted or the folder was packed since that message arrived, it will fail. # # I've been using this (or earlier versions) for about 2 years now and my database # is about 5000 entries; I find it EXTERMELY useful when I cannot quite remember the email # address of that guy I got a message from 6 months ago and need to reply to, but # I remember it was "Ted something". # # It takes a little while to load the browser window (at least for me, sorting 5000 # strings and then inserting them into a listbox takes a while), but then it "stays" # even if you dismiss it so it's not too painful. # # Enjoy; if you find this useful please let me know; if you make it better # please send me the code. # # --Berry Kercheval, Xerox PARC, March 1996 (kerch@parc.xerox.com) ######################################################################### # # These variables control the setup # set addrVersion {$Revision$} # Addr_debug, if ==1, enables printing messages while this stuff runs. # Set Addr_debug 1 in your user.tcl before invoking Addr_Init to enable debug messages if {0 == [info exists Addr_debug]} { set Addr_debug 0 } # # Addr_Init loads the database file at startup time, and arranges the # partial-address-expansion keybinding. # proc Addr_Init {} { global env global addrFile global homeDir global addr_list # addrFile is the name of the file the address database is kept in set addrFile "exmh_addrs" # homeDir is the directory the database is kept in. set homeDir "$env(HOME)/.exmh" # tell exmh about our preference items and initialize them Preferences_Add "Address Database" "These settings affect the behavior of the address database. See also the key binding for \"addrexpand\" that is set in the Bindings... dialog Simple Edit." { { addr_db(enabled) addressdbEnabled ON "Automatic address saving" "If set, From addresses are remembered and available in an address browser." } { addr_db(hideexcluded) addressdbHideExcluded ON "Hide excluded addresses" "If set, addresses excluded from the expansion process will not be displayed by the Address DB Browser." } { addr_db(checkpoint_on_folder_change) addressdbFolderChangeCheckpoint ON "Checkpoint on Folder Change" "If set, Exmh will save your address file whenever you visit a new folder." } { addr_db(searchlist) addressdbSearchlist {Addr_FullNameMatch Addr_Lookup Alias_Lookup LDAP_Lookup} "Expand methods to use" "A list of TCL procs, separated by spaces, which will be called sequentially to try to expand the address. Valid choices are \"Addr_FullNameMatch\" to search full names, \"Addr_Lookup\" to search for mail addresses, \"Alias_Lookup\" to search your MH/exmh alias list, and LDAP_Lookup to use an LDAP server." } { addr_db(ldap_server) addressdbLDAPServer {-h localhost} "LDAP Server" "The server to send LDAP queries to, prefixed with any necessary command-line option flags for the LDAP search program." } { addr_db(ldap_searchbase) addressdbLDAPSearchBase {} "LDAP Search Root" "The root DN under which to conduct LDAP searches, prefixed with any necessary command-line option flags (usually -b)." } { addr_db(ldap_encoding) addressdbLDAPEncoding {utf-8} "LDAP Encoding" "The character encoding used by the LDAP server." } { addr_db(ldap_searchprog) addressdbLDAPSearchprog {ldapsearch -x} "LDAP search program" "The command-line LDAP search program, with arguments." } { addr_db(filter_regexp) addressdbFilterRegexp {} "Regular expression filter" "If set, addresses matching this regular expression pattern will not be saved in the database." } { addr_db(skip_folders) addressdbFoldersSkip {} "Folders to ignore" "A list of one or more folders separated by spaces. Exmh will not save addresses from the mail in the folders in this list. An empty list will allow Exmh to add addresses from every folder. Groups of folders may be specified using * as a wild card anywhere in a folder name." } { addr_db(filter_alternate_mailboxes) addressdbFilterAltMailboxes ON "Ignore alternate mailboxes" "If set, addresses that match the names specified as \"Alternate mailboxes\" in your MH profile will not be saved." } { addr_db(key_force_save) addressdbForceSave "Key to save an address" "Key which, if pressed, will cause the address from the current message to be stored regardless of any filtering specified. This key is only active in the main exmh window so it may be the same as the \"Key to expand addresses\" without conflict. Pressing this key stores an address in the database even if it would have been filtered (not stored) due to matching \"Regular expression filter\", \"Folders to ignore\", or one of your alternate mailboxes." } { addr_db(standard_address_format) addressdbStandardFormat ON "Use \"address (Full Name)\" Format" "If on, use \"address (Full Name)\" format for expanded addresses. Otherwise, use \"Full Name
\" format." } { addr_db(remove_entries) addressdbRemoveEntries OFF "Remove Old Entries" "If on, remove old entries from the database" } { addr_db(remove_days) addressdbRemoveDays {} "Days Until Removal" "Number of days until inactive entry is removed" } { addr_db(remove_invalid_date) addressdbRemoveInvalidDate OFF "Remove Invalid Date" "If on, delete any entry with a non-null, but invalid date" } } #addr_db is an array used for keeping state. #make this an array from the get-go and set the default pref... global addr_db set addr_db(init) 1; if ![info exists addr_db(curmethod)] {set addr_db(curmethod) 0} if ![info exists addr_db(laststring)] {set addr_db(laststring) ""} if ![info exists addr_db(lastfound)] {set addr_db(lastfound) ""} if ![info exists addr_db(changed)] {set addr_db(changed) 0} if ![info exists addr_db(filterstring)] {set addr_db(filterstring) ""} if ![info exists addr_db(remove_entries)] {set addr_db(remove_entries) 0} if ![info exists addr_db(remove_days)] {set addr_db(remove_days) ""} if ![info exists addr_db(remove_invalid_date)] {set addr_db(remove_invalid_date) 0} trace variable addr_db(hideexcluded) w Addr_Browse_Exclude_Change Addr_LoadDB } # # Hook_MsgShow is called when exmh displays a message. We parse out the # From: header and call Addr_Save to update the entry in the database. # proc Hook_MsgShowAddr {path headervar } { upvar $headervar header global addr_db set addr_db(last_seen) [list $path $header(0=1,hdr,from) $header(0=1,hdr,date)] if {! $addr_db(enabled)} { return } Addr_Save [MsgParseFrom $header(0=1,hdr,from)] $path \ $header(0=1,hdr,from) $header(0=1,hdr,date) } # # Hook_FolderChange is called when a new folder is visited. Save the # database then too. # proc Hook_FolderChangeAddr {newfolder} { global addr_db if {$addr_db(changed) && $addr_db(checkpoint_on_folder_change)} { Addr_SaveFile } } # # Hook_CheckPoint is called when exmh checkpoints its state. Save the # database here. # proc Addr_CheckPoint {} { Addr_SaveFile } ##### # # Address_Init and the address Hook procedures are moved to extrasInit.tcl # #### ######################################################################## # # This one is bound to a key of the user's choosing to force-save # the from address of the current message (info stored in last-seen by # the Hook_MsgShow routine above. # proc Address_Save {} { global addr_db AddrDebug "Force save $addr_db(last_seen)" Addr_Save [MsgParseFrom [lindex $addr_db(last_seen) 1]] \ [lindex $addr_db(last_seen) 0] \ [lindex $addr_db(last_seen) 1] \ [lindex $addr_db(last_seen) 2] \ "force" } # SaveTo saves the current address on the to line # proc SaveTo { w } { global addr_db Exmh_Status "SaveTo: w=$w" set line [string trim [$w get {insert linestart} {insert lineend}]] ## AddrDebug " got line \"$line\"" # Only allows expansion on addressable header lines. if [regexp -nocase {^(to: *|resent-to: *|cc: *|resent-cc: *|bcc: *|dcc: *)(.*)} $line t0 t1 t2] { ## AddrDebug " matched! keep is \"$t1\", partial name=\"$t2\"" if [regexp -indices ",?.*, *" $t2 t0] { set t0 [lindex $t0 end] ## AddrDebug "got comma at $t0" set t3 [string range $t2 0 $t0] append t1 $t3 set t2 [string range $t2 [expr $t0 + 1] end] ## AddrDebug " multi, will keep \"$t1\", new partial name=\"$t2\"" } # Save address ($t2) Addr_Save [MsgParseFrom $t2] "NEW" $t2 "NULL" "force" } else { Exmh_Status "Error in name expansion: not on To: field" return } } ######################################################################## # # These are the "real" database procs. # # # This is "magically" executed when exmh is setting up # keystroke bindings for the main window # proc Addr_Bindings { w } { global addr_db if {$addr_db(key_force_save) != ""} { AddrDebug "binding for $w" Bind_Key $w $addr_db(key_force_save) {Address_Save ; break} } } # # Addr_LoadDB does the real work to load the database file. # proc Addr_LoadDB { {ldmsg ""} } { global addr_db global addrFile global homeDir global addr_list AddrDebug "AddrDB: loading database..." catch {source $homeDir/$addrFile} set addr_db(changed) 0 if {[array size addr_list] == 0} { set addr_list(noone@nowhere.nada.zip) 1; #null array, put in a dummy } AddrDebug "AddrDB: loading database...done." Addr_Browse_LoadListbox $ldmsg } # # Addr_SaveFile saves the database into a unix file # proc Addr_SaveFile { {force 0} } { global addr_list addr_db global addrFile global homeDir if {0 == $addr_db(changed) && 0 == $force} return Exmh_Status "Saving address database..." if {$addr_db(remove_days) == ""} { set expiration 0 } else { set expiration [expr [clock seconds] - (60*60*24*$addr_db(remove_days))] } set fd [open "$homeDir/.exmh_addr_tmp" w] foreach i [array names addr_list] { # rfc2822: day name is optional, and comments after the timezone offset regsub {^[a-zA-Z]+, } [lindex $addr_list($i) 1] {} mailtime; regsub {\(.+\)\s*$} $mailtime {} mailtime; global tcl_version if {[catch { set mailsec [clock scan $mailtime -format "%d %b %Y %T %z"] if {$addr_db(remove_entries) == 1 && $addr_db(enabled) == 1 && $expiration > 0 && [lindex $addr_list($i) 1] != "" && $mailsec < $expiration} { unset addr_list($i) } else { puts $fd [list set addr_list($i) $addr_list($i)] }} response]!= 0} { if {$addr_db(remove_invalid_date)} { unset addr_list($i) } else { puts $fd [list set addr_list($i) $addr_list($i)] } } } close $fd # the first time the address file won`t exist yet... if [file exists $homeDir/$addrFile] { Mh_Rename $homeDir/$addrFile $homeDir/$addrFile.bak } Mh_Rename $homeDir/.exmh_addr_tmp $homeDir/$addrFile set addr_db(changed) 0 Exmh_Status "Saving address database...done." } # # Field level extract and set routines # proc Addr_Entry_IsExcluded {key} { global addr_list set excluded 0 if [catch {set item $addr_list($key)} err] { Exmh_Status "Address DB: Addr_Entry_IsExcluded lookup error for $key" } else { if {1==[lindex $item 4]} { set excluded 1 } } return $excluded } proc Addr_Entry_SetExcluded {key} { global addr_list addr_db if [catch {set item $addr_list($key)} err] { Exmh_Status "Address DB: Addr_Entry_SetExcluded lookup error for $key" } else { if {5 == [llength $item]} { set addr_list($key) "[lrange $item 0 3] 1" } else { set addr_list($key) "$item 1" } set addr_db(changed) 1 } return } proc Addr_Entry_UnsetExcluded {key} { global addr_list addr_db if [catch {set item $addr_list($key)} err] { Exmh_Status "Address DB: Addr_Entry_UnsetExcluded lookup error for $key" } else { if {5 == [llength $item]} { set addr_list($key) [lrange $item 0 3] set addr_db(changed) 1 } } return } proc Addr_Entry_ToggleExcluded {key} { if [Addr_Entry_IsExcluded $key] { Addr_Entry_UnsetExcluded $key } else { Addr_Entry_SetExcluded $key } } # Format an address with full name. The result may be either # # address (full name) # or # full name
# # depending on the state of the standard_address_format flag. proc Addr_Entry_FormatForMail {key} { global addr_list addr_db if [catch {set item $addr_list($key)} err] { return $key } set fullname [lindex $item 2] regsub ,$ $fullname {} fullname_less_comma if {0 == [string length "$fullname_less_comma" ]} { set formatted "$key" } else { if {$addr_db(standard_address_format)} { set formatted "$key ($fullname_less_comma)" } else { # If there are characters in the name that require quoting, # quote the string. if [string match {*[<>.,'*?]*} $fullname_less_comma] { set formatted "\"$fullname_less_comma\" <$key>" } else { set formatted "$fullname_less_comma <$key>" } } } return $formatted } proc Addr_Entry_FormatForListbox {key} { global addr_list if [catch {set item $addr_list($key)} err] { return $key } set fullname [lindex $item 2] regsub ,$ $fullname {} fullname_less_comma if [Addr_Entry_IsExcluded $key] { set formatted [format "%-24.24s- <%s>" $fullname_less_comma $key ] } else { set formatted [format "%-25.25s <%s>" $fullname_less_comma $key ] } return $formatted } # # Addr_Save updates the database entry when a new message is read. # proc Addr_Save {from path rawfrom date {forcesave "not"}} { global addr_db global addr_list global exmh global mhProfile if {[string compare $forcesave "force"] != 0} { if {$addr_db(skip_folders) != ""} { set filter_list [split $addr_db(skip_folders) " "] # AddrDebug " folder filter list is \"$filter_list\"" foreach i $filter_list { if {[string length $i] > 0} { # AddrDebug "Matching \"$exmh(folder)\" for \"$i\"" if [string match $i $exmh(folder)] { AddrDebug " folder filter eliminated $exmh(folder)" return } } } } if {$addr_db(filter_alternate_mailboxes) != 0} { catch {unset filter_list} catch { set filter_list [split $mhProfile(alternate-mailboxes) ", "] } if [info exists filter_list] { # Filter out all of the user's alternate mailboxes # AddrDebug "alternate mailboxes \"$mhProfile(alternate-mailboxes)" set filter_list [split $mhProfile(alternate-mailboxes) ", "] # AddrDebug " list \"$filter_list\"" foreach i $filter_list { if {[string length $i] > 0} { if [string match $i $from] { AddrDebug " alternate mailbox filter eliminated $from" return } } } } } if {$addr_db(filter_regexp) != ""} { # AddrDebug "filtering $addr_db(filter_regexp)" if [regexp -nocase -- $addr_db(filter_regexp) $from] { AddrDebug " regexp filter eliminated $from" return } } } set addr_db(changed) 1 set newentry 0 if [info exists addr_list($from)] { Exmh_Status "Updating address \"$from\"." if {[string length [Addr_ParseFrom $rawfrom]] == 0} { set newone [list $path $date \ [lindex $addr_list($from) 2] $rawfrom [Addr_Entry_IsExcluded $from]] } else { set newone [list $path $date \ [Addr_ParseFrom $rawfrom] $rawfrom [Addr_Entry_IsExcluded $from]] } } else { Exmh_Status "Saving address \"$from\"." set newone [list $path $date \ [Addr_ParseFrom $rawfrom] $rawfrom] set newentry 1 } set addr_list($from) $newone if {$newentry} { # Gotta catch this in case there's no browser window catch { $addr_db(win) insert end [Addr_Entry_FormatForListbox $from] } } } # # Addr_KeyExpand expands a partial address in response to a key binding # proc Addr_KeyExpand { w } { global addr_db AddrDebug "Addr_KeyExpand: w=$w $addr_db(searchlist)" set line [string trimright [$w get {insert linestart} {insert lineend}]] ## AddrDebug " got line \"$line\"" # Only allows expansion on addressable header lines. #old regexp: regexp -nocase {^(to: *|resent-to: *|cc: *|resent-cc: *|bcc: *|dcc: *)(.*)} $line t0 t1 t2 if {[$w compare insert <= hlimit] && \ [regexp -nocase {^([-a-z]+: *)?(.*)} $line t0 t1 t2]} { ## AddrDebug " matched! keep is \"$t1\", partial name=\"$t2\"" if {[regexp -indices ",?.*, *" $t2 t0] || \ [regexp -indices "^ +" $t2 t0]} { set t0 [lindex $t0 end] ## AddrDebug "got comma at $t0" set t3 [string range $t2 0 $t0] append t1 $t3 set t2 [string range $t2 [expr $t0 + 1] end] ## AddrDebug " multi, will keep \"$t1\", new partial name=\"$t2\"" } if {[string compare $addr_db(lastfound) $t2] != 0 \ || $addr_db(curmethod) >= [llength $addr_db(searchlist)]} { Exmh_Status "Resetting start method" catch {destroy $w.addrs} set addr_db(expansion) {} set addr_db(curmethod) 0 set addr_db(laststring) $t2 } else { if {$addr_db(curmethod) != 0} { set t2 $addr_db(laststring) } } foreach proc [lrange $addr_db(searchlist) $addr_db(curmethod) end] { incr addr_db(curmethod) Exmh_Status "$proc $t2" set result [busy $proc $t2] if {[string compare $result ""] == 0} continue if {[llength $result] == 1} { # unique match $w delete {insert linestart} {insert lineend} $w insert insert [format "%s%s" $t1 [lindex $result 0]] set addr_db(lastfound) [lindex $result 0] catch {destroy $w.addrs} } else { # must be multiple hits AddrDebug " Multiple hits: $result" set addr_db(lastfound) $t2 set new [AddrShowDialog $w $result] # if no selection is made, leave the string where it is if [ string compare $new "" ] { set addr_db(lastfound) $new $w delete {insert linestart} {insert lineend} $w insert insert [format "%s%s" $t1 $new] } } break } } else { Exmh_Status "Error in name expansion: not on supported field" return } } proc Alias_Lookup {n} { global aliases Aliases_Load set t2 [string trim $n] if {[string length [array names aliases $t2]] == 0} { Exmh_Status "No match found for \"$t2\"" return {} } else { Exmh_Status "Found alias: \"$aliases($t2)\"" if {1 == [llength $aliases($t2)] && \ 0 != [string compare "\{" [string range $aliases($t2) 0 0]] } { return [list [Addr_Entry_FormatForMail $aliases($t2)]] } # Note: cannot use Address_Entry_FormatForMail here since contents # of alias is too unpredicatble. May be a list of names, may be # a preformatted fullname and address. So send it back as-is return $aliases($t2) } } proc Addr_FullNameMatch {n} { global addr_list Exmh_Status "Matching on full names with $n..." set result {} set pat {} append pat [string trim $n] foreach i [ array names addr_list] { if {1 == [Addr_Entry_IsExcluded $i]} continue set elt $addr_list($i) set fn [lindex $elt 2] # puts stdout "matching against $fn (elt = $elt)" if [catch {set match [regexp -nocase -- $pat $fn t0]}] { Exmh_Status "Fullname expansion error: Invalid regexp \"$pat\"" return {} } if {$match} { AddrDebug " fullname match on $fn" lappend result "[Addr_Entry_FormatForMail $i]" } } if {[llength $result] > 0} { return $result } else { Exmh_Status "Matching on full names with \"$pat\"...none found" return {} } } proc LDAP_Lookup {n} { global addr_db # Make sure the ldap_server variable has been set in the preferences. if { ($addr_db(ldap_server) == {}) || ($addr_db(ldap_searchbase) == {}) } { return {} } Exmh_Status "Querying $addr_db(ldap_server) from $addr_db(ldap_searchbase) with $n via $addr_db(ldap_searchprog)..." set query "\"(|(cn=*$n*)(mail=*$n*)(sn=*$n*)(givenname=*$n*))\"" if {[catch {set query "[encoding convertto $addr_db(ldap_encoding) "$query"]"} err]} { Exmh_Debug "LDAP_Lookup encoding convertto: $err" } if [catch {set ldap_results [eval exec $addr_db(ldap_searchprog) [string trim $addr_db(ldap_server)] \ $addr_db(ldap_searchbase) \ "$query" cn mail]} err] { Exmh_Status "Error executing $addr_db(ldap_searchprog): $err" return {} } if {[catch {set ldap_results [encoding convertfrom utf-8 "$ldap_results"]} err]} { Exmh_Debug "LDAP_Lookup encoding convertfrom: $err" } # The return from ldapsearch will be something like this: # # cn=Lastname, Firstname # mail=foo@nowhere.com # # cn=Anotherlastname, Anotherfirstname # mail=bar@nowhere.com # # ... set result {} foreach i [split $ldap_results \n ] { if [regexp -nocase {^mail[=:] *([^,]*)$} $i dummy email] { lappend result "[LDAP_Entry_FormatForMail $email $name]" } elseif [regexp -nocase {^cn[=:] *(.*)$} $i dummy tmp] { set name $tmp } } return $result } proc LDAP_Entry_FormatForMail { email name } { global addr_db if {$addr_db(standard_address_format)} { set formatted "$email ($name)" } else { # If there are characters in the name that require quoting, # quote the string. if [string match {*[<>.,'*?]*} $name] { set formatted "\"$name\" <$email>" } else { set formatted "$name <$email>" } } return $formatted } proc Addr_Lookup { n } { global addr_list AddrDebug "Addr_Lookup: looking for $n" if {[string compare $n ""] == 0} { Exmh_Status "Address expansion error: null string!" return {} } set result {} set pat {} append pat [string trim $n] AddrDebug " using pattern \"$pat\"" foreach i [array names addr_list] { if {1 == [Addr_Entry_IsExcluded $i]} continue set elt $addr_list($i) if [catch {set match [regexp -nocase -- $pat $i t0]}] { Exmh_Status "Address expansion error: Invalid regexp \"$pat\"" return {} } if {$match} { AddrDebug " match on $i" set fn [lindex $elt 2] lappend result "[Addr_Entry_FormatForMail $i]" } } AddrDebug "Addr_Lookup: result is $result" return $result } # # Addr_ParseFrom takes a raw From: header and return the fullname. # it should work on lines of the form: # ## Berry Kercheval ## kerch@parc.xerox.com (Berry Kercheval) proc Addr_ParseFrom { fromline } { # AddrDebug "Addr_ParseFrom: working on $fromline" set line [string trim $fromline] # if it's "xxx "... if [regexp {([^<]*)(<.*>)} $line t1 t2 t3] { # AddrDebug " Matched: ( $t1 )( $t2 )( $t3 )" set token [string trim $t2 ] } else { # nope, try foo@bar (xxx) # AddrDebug " Not xxx , try foo@bar (xxx)" if [regexp {^([^\(]*)(\(.*\))[^\)]*$} $line t1 t2 t3] { # AddrDebug " Matched: ( $t1 )( $t2 )( $t3 )" set token $t3 } else { # none of the above, give up. set token {} } } # AddrDebug " result is $token" # set token [string trim $token "\"()"] if [regexp {^\((.*)\)$} $token t1 t2] { set token $t2 } if [regexp {^\"(.*)\"$} $token t1 t2] { set token $t2 } # AddrDebug " trimmed result is $token" return $token } # # Debug support # proc AddrDebug { s {nonewline {}}} { global Addr_debug if {$Addr_debug == 1} { if {[string compare $nonewline ""] == 0} { puts stdout $s } else { puts stdout $s nonewline } } } proc AddrShowDialog {w list} { global addr_db catch {destroy $w.addrs} set f [frame $w.addrs -bd 4 -relief ridge] frame $f.top -relief flat set l [listbox $f.top.lb -bd 4 -width 50 -height 10] bind $l "\ AddrShowDialogDone $f $l ;\ break \ " bind $l "\ AddrShowDialogCancel $f ;\ break \ " focus $f.top.lb $f configure -cursor left_ptr foreach i $list { $l insert end $i } pack $f.top.lb -expand true -fill both -side left if {[llength $list] > 10} { $f.top.lb configure -yscrollcommand "$f.top.sy set" scrollbar $f.top.sy -width 15 -command [list $l yview] pack $f.top.sy -expand true -fill y -side left } pack $f.top -expand true -fill both frame $f.but -bd 10 -relief flat pack $f.but -expand true -fill both Widget_AddBut $f.but ok "Done" [list AddrShowDialogDone $f $l] {left filly} Widget_AddBut $f.but can "Cancel" [list AddrShowDialogCancel $f] {right filly} Widget_PlaceDialog $w $f tkwait window $f if [info exists addr_db(expansion)] { Exmh_Status "returning $addr_db(expansion)" return $addr_db(expansion) } else { return {} } } proc AddrShowDialogDone {f l} { global addr_db set result [$l curselection] if {[string compare $result ""] != 0} { set result [lindex $result 0] set name [$l get $result] AddrDebug "Selected: $result ($name)" set addr_db(expansion) $name } else { AddrDebug "Selected: " set addr_db(expansion) "" } AddrDebug "selected $addr_db(expansion)" focus [winfo parent $f] catch {destroy $f} } proc AddrShowDialogCancel {f} { global addr_db set addr_db(expansion) "" AddrDebug "selected $addr_db(expansion)" focus [winfo parent $f] catch {destroy $f} } proc Addr_Browse { {state normal} } { global exwin global addr_br global addr_db global addr_list global Addr_debug set t .addr_br set f .addr_br.but set ldmsg "Creating Address Browser..." if [Exwin_Toplevel .addr_br "Address DB Browser" Addr_Br] { # Reconfigure the Dismiss button created by Exwin_Toplevel $f.quit configure -takefocus {} -command {Exwin_Dismiss .addr_br} # Create the "Selected..." menu (initially disabled) set menu_sel [Widget_AddMenuB $f selmenu "Selected..." {right padx 1 filly} ] $f.selmenu configure -takefocus {} -state disabled set addr_db(selmenu) $f.selmenu Widget_AddMenuItem $menu_sel "Mail To" \ { Addr_Browse_Selected MailTo } Widget_AddMenuItem $menu_sel "Edit" \ { Addr_Browse_Selected Edit } Widget_AddMenuItem $menu_sel "Delete" \ { Addr_Browse_Selected Delete } Widget_AddMenuItem $menu_sel {Toggle Exclude} \ { Addr_Browse_Selected Exclude } Widget_AddMenuItem $menu_sel {View Last Msg} \ { Addr_Browse_Selected ViewLastMsg } # Create the "Database..." menu set menu_db [Widget_AddMenuB $f dbmenu "Database..." {right padx 1 filly} ] $f.dbmenu configure -takefocus {} Widget_AddMenuItem $menu_db "Save" \ { Addr_SaveFile 1 } Widget_AddMenuItem $menu_db "Reload" \ { Addr_Browse_Reload } Widget_AddMenuItem $menu_db "Sort" \ { Addr_Browse_LoadListbox "Sorting database..." normal } if { $Addr_debug == 1 } { Widget_AddBut $f ldsrc "LdSrc" { Addr_Load_Source } } # Create the New button Widget_AddBut $f new "New" { Addr_Browse_New } # Finally, create the Help button Widget_AddBut $f help "Help" { Help AddrEdit } $f.help configure -takefocus {} # would be nice if the listbox was a set of coordinated list boxes, # one column for each field, with headings and options to pick which # to display and which to sort on. # Create the listbox and a scroll bar to help it set addr_db(win) [listbox $t.lb \ -selectmode extended \ -height 20 -width 65 \ -relief sunken \ -yscrollcommand [list $t.sb set] ] scrollbar $t.sb -orient vertical -command [list $addr_db(win) yview] # Create the filter/find entry field Addr_LabelledTextField $t.find Find 0 "set addr_db(filterstring) \[$t.find.entry get \]; Addr_Browse_LoadListbox {Finding...} normal" $t.find.entry insert 0 $addr_db(filterstring) # Mouse button bindings for the listbox bind $addr_db(win) {Addr_Browse_Selected Edit} bind $addr_db(win) {Addr_Browse_TrackSel} bind $addr_db(win) {Addr_Browse_TrackSel} bind $addr_db(win) {Addr_Browse_Selected Exclude} # Menu key accelerators for the toplevel, # but don't do 'em if in the find entry field bind $t { if {0 != [string compare "%W" ".addr_br.find.entry"]} {Addr_Browse_Selected Exclude} } bind $t { if {0 != [string compare "%W" ".addr_br.find.entry"]} {Addr_Browse_Selected MailTo} } bind $t { if {0 != [string compare "%W" ".addr_br.find.entry"]} {Addr_Browse_Selected Delete} } bind $t { if {0 != [string compare "%W" ".addr_br.find.entry"]} {Addr_SaveFile 1} } bind $t { if {0 != [string compare "%W" ".addr_br.find.entry"]} {Addr_Browse_Reload} } # Adjust packing and filling pack $t.find -side bottom -fill x pack $t.sb -side $exwin(scrollbarSide) -fill y pack $addr_db(win) -expand true -fill both } if {0 == [string compare "$state" "normal"]} { Exmh_Status $ldmsg } # All built, now load up the listbox Addr_Browse_LoadListbox $ldmsg $state # Initial focus to the listbox so accelerators work. focus $addr_db(win) if {0 == [string compare "$state" "normal"]} { Exmh_Status "$ldmsg done" } } proc Addr_Browse_TrackSel {} { global addr_db catch { ;# windows may not exist if { 0 != [string length [$addr_db(win) curselection]] } { $addr_db(selmenu) configure -state normal } else { $addr_db(selmenu) configure -state disabled } } } proc Addr_Browse_LoadListbox { {ldmsg ""} {state normal}} { global addr_db addr_list if {![info exists addr_db(win)] || ![winfo exists $addr_db(win)]} return if {[catch {regexp -nocase -- $addr_db(filterstring) {}} err]} { Exmh_Status $err ;# bad pattern return } $addr_db(win) delete 0 end if {0 == [string compare "$state" "normal"]} { Exmh_Status "$ldmsg getting names..." } set l {} foreach i [array names addr_list] { if {$addr_db(hideexcluded) == 0 || [Addr_Entry_IsExcluded $i] == 0} { lappend l [Addr_Entry_FormatForListbox $i] } } if {[llength $l]} { if {0 == [string compare "$state" "normal"]} { Exmh_Status "$ldmsg sorting names..." } set l [lsort $l] set n 0 set whiz [list | \\ - /] set w 0 if {[string length $addr_db(filterstring)] > 0} { foreach i $l { if [regexp -nocase -- $addr_db(filterstring) $i] { $addr_db(win) insert end $i } incr n if { 0==($n%100) } { if {0 == [string compare "$state" "normal"]} { Exmh_Status "$ldmsg inserting names... [lindex $whiz $w]" } set w [expr {($w+1)%4}] } } } else { foreach i $l { $addr_db(win) insert end $i incr n if { 0==($n%100) } { if {0 == [string compare "$state" "normal"]} { Exmh_Status "$ldmsg inserting names... [lindex $whiz $w]" } set w [expr {($w+1)%4}] } } } } if {0 == [string compare "$state" "normal"]} { Exmh_Status "$ldmsg done" update idletasks } } # Called by trace variable magic when user changes Show Excluded preference item proc Addr_Browse_Exclude_Change {name element op} { global addr_db catch {Exmh_Debug Event addr_db win is $addr_db(win)} Addr_Browse_LoadListbox {} silently return } proc Addr_Browse_Clip {sel} { global addr_db addr_list mhProfile set victim [MsgParseFrom [$addr_db(win) get $sel]] set last [lindex $addr_list($victim) 0] # since there may be recursive folders, match the MH Path # off the front, the message number off the end and the rest must be the folder. set pat "($mhProfile(path))/(.+)/(\[0-9\]+)\$" if [regexp -- $pat $last match path folder msg] { Msg_Clip $folder $msg } else { Exmh_Status "ViewLastMsg cannot find $last" } } proc Addr_Browse_Reload {} { global addr_db addr_list set ldmsg "Reloading address database..." if $addr_db(changed) { if [Addr_Browse_ChangedDialog $addr_db(win)] { Exmh_Status $ldmsg unset addr_list Addr_LoadDB $ldmsg Exmh_Status "$ldmsg done." } else { Exmh_Status "$ldmsg aborted." } } else { Exmh_Status $ldmsg unset addr_list Addr_LoadDB $ldmsg Exmh_Status "$ldmsg done." } } proc Addr_Browse_ChangedDialog {w} { global addr_db set f [frame $w.addrch -bd 4 -relief ridge] Exmh_Status "$f" Widget_AddBut $f ok "Yes, this will lose all changes" "\ set addr_db(changeresult) 1 ;\ destroy $f " \ left Widget_AddBut $f no "No, do not reload" "\ set addr_db(changeresult) 0 ;\ destroy $f " \ right Widget_PlaceDialog $w $f tkwait window $f AddrDebug "Addr_Browse_ChangedDialog returns $addr_db(changeresult)" return $addr_db(changeresult) } proc Addr_LabelledTextField { name label width command } { frame $name label $name.label -text $label -width $width -anchor w eval {entry $name.entry -relief sunken -width 50 } pack $name.label -side left pack $name.entry -side right -fill x -expand true bind $name.entry "$command ; break" return $name.entry } # Interate across all selected items applying a command proc Addr_Browse_Selected { { op Noop } } { global addr_db addr_list set to {} ; set sep "" foreach sel [lsort -decreasing -integer [$addr_db(win) curselection]] { switch $op { MailTo { append to $sep[Addr_Entry_FormatForMail \ [MsgParseFrom [$addr_db(win) get $sel]]] set sep ", " } Edit { Addr_Browse_Edit $sel } Delete { set victim [MsgParseFrom [$addr_db(win) get $sel]] if [catch {unset addr_list($victim)} val] { Exmh_Status "Address DB: can't delete: $val" } else { set addr_db(changed) 1 # update browser window... $addr_db(win) delete $sel Exmh_Status "Address DB: Deleted $victim" } } Exclude { set victim [MsgParseFrom [$addr_db(win) get $sel]] Addr_Entry_ToggleExcluded $victim # update browser window... $addr_db(win) delete $sel if {$addr_db(hideexcluded) == 0 || [Addr_Entry_IsExcluded $victim] == 0} { $addr_db(win) insert $sel [Addr_Entry_FormatForListbox $victim] } } ViewLastMsg { Addr_Browse_Clip $sel } } } if {[string length $to] > 0} { Msg_CompTo $to } Addr_Browse_TrackSel } proc Addr_Browse_Edit {sel} { global addr_db addr_list set victim [MsgParseFrom [$addr_db(win) get $sel]] if [catch {set item $addr_list($victim)} err] { Exmh_Status "Address DB: Addr_Browse_Edit lookup error for $victim" return } set name [lindex $item 2] set addr [lindex $item 3] set last [lindex $item 0] set date [lindex $item 1] set exclude [Addr_Entry_IsExcluded $victim] unset item set t .addr_ed set id 0 for {set id 1} {$id < 21} {incr id} { AddrDebug "winfo exists $t$id is [winfo exists $t$id]" if [winfo exists $t$id] continue append t $id break } if [winfo exists $t] { Exmh_Status "Too many editors open, close one or more and try again" return } if [Exwin_Toplevel $t "Address DB editor" Addr_Ed] { set f $t.but $t.but.quit configure -text Cancel -command "Addr_Edit_Dismiss $t" $t configure -width 500 Widget_AddBut $f save "Save" "Addr_Edit_Save $t $sel" Widget_AddBut $f delete "Delete" "Addr_Edit_Delete $t $sel" Widget_AddBut $f last "ViewLastMsg" "Addr_Browse_Clip $sel" set e [Widget_AddBut $f ignore "Exclude" "Addr_Edit_Exclude $t $sel"] set n [Addr_LabelledTextField $t.name "Full Name" 12 "Addr_Edit_Save $t $sel" ] set a [Addr_LabelledTextField $t.address "Address" 12 "Addr_Edit_Save $t $sel" ] set l [Addr_LabelledTextField $t.lastMsg "Last Message" 12 "Addr_Edit_Save $t $sel" ] set d [Addr_LabelledTextField $t.date "Date" 12 "Addr_Edit_Save $t $sel" ] pack $t.name $t.address $t.lastMsg $t.date } $n delete 0 end; $n insert 0 $name $a delete 0 end; $a insert 0 $addr $l delete 0 end; $l insert 0 $last $d delete 0 end; $d insert 0 $date if {$exclude == 1} { $e config -text "Include" AddrDebug "$e config -text Include" } else { $e config -text "Exclude" AddrDebug "$e config -text Exclude" } } proc Addr_Browse_New {} { global addr_db addr_list set t .addr_ed set id 0 for {set id 1} {$id < 21} {incr id} { AddrDebug "winfo exists $t$id is [winfo exists $t$id]" if [winfo exists $t$id] continue append t $id break } if [winfo exists $t] { Exmh_Status "Too many editors open, close one or more and try again" return } if [Exwin_Toplevel $t "New DB address" Addr_Ed] { set f $t.but $t.but.quit configure -text Cancel -command "Addr_Edit_Dismiss $t" $t configure -width 500 Widget_AddBut $f save "Save" "Addr_New_Save $t" Addr_LabelledTextField $t.name "Full Name" 12 "Addr_New_Save $t" Addr_LabelledTextField $t.address "Address" 12 "Addr_New_Save $t" pack $t.name $t.address } } proc Addr_New_Save {winname} { global addr_db addr_list set name [$winname.name.entry get] set addr [$winname.address.entry get] set last "" set date "" set index [MsgParseFrom $addr] # NEED TO STUFF new NAME into entry! set addr [format "%s <%s>" $name $index] Exmh_Status "Updating address \"$index\"." set addr_db(changed) 1 set addr_list($index) [list $last $date \ [Addr_ParseFrom $addr] $addr] # update browser window... $addr_db(win) insert end [Addr_Entry_FormatForListbox $index] # make it all go away so we can redo it next time. Addr_Edit_Dismiss $winname } proc Addr_Load_Source {} { global env # HACK HACK HACK!!! source "~/.tk/exmh/addr.tcl" } ######################################################################## # # Address Editor Routines # proc Addr_Edit_Exclude {winname sel} { global addr_db addr_list set addr [$winname.address.entry get] set victim [MsgParseFrom $addr] Exmh_Status "Updating address \"$victim\"." Addr_Entry_ToggleExcluded $victim set exclude [Addr_Entry_IsExcluded $victim] # update browser window... $addr_db(win) delete $sel if {$addr_db(hideexcluded) == 0 || $exclude == 0} { $addr_db(win) insert $sel [Addr_Entry_FormatForListbox $victim] } # make it all go away so we can redo it next time. Addr_Edit_Dismiss $winname } proc Addr_Edit_Save {winname sel} { global addr_db addr_list set name [$winname.name.entry get] set addr [$winname.address.entry get] set last [$winname.lastMsg.entry get] set date [$winname.date.entry get] set index [MsgParseFrom $addr] # NEED TO STUFF new NAME into entry! set addr [format "%s <%s>" $name $index] Exmh_Status "Updating address \"$index\"." set addr_db(changed) 1 set addr_list($index) [list $last $date \ [Addr_ParseFrom $addr] $addr] # update browser window... $addr_db(win) delete $sel $addr_db(win) insert $sel [Addr_Entry_FormatForListbox $index] # make it all go away so we can redo it next time. Addr_Edit_Dismiss $winname } proc Addr_Edit_Delete { winname sel } { global addr_db addr_list set addr [$winname.address.entry get] set index [MsgParseFrom $addr] $addr_db(win) delete $sel unset addr_list($index) Addr_Edit_Dismiss $winname } proc Addr_Edit_Abort {} { global addr_db Addr_Edit_Dismiss } proc Addr_Edit_Dismiss { winname } { Exwin_Dismiss $winname destroy $winname } ######################################################################## # # done loading... # if {$Addr_debug} { puts stdout "done." } exmh-2.9.0/lib/widgetText.tcl0000644000170700017070000002257213201227060015420 0ustar valdisvaldis# widgetText.tcl # # Layer over the TK text widget that provides contrained scrolling # and 1-to-1 draging. # # Based on code contributed by John Robert Loverso # # Copyright (c) 1993 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. proc Widget_TextInit {} { # Preferences stuff moved to exwin.tcl # for the sake of the user interface. } proc Widget_TextInitText {t} { global widgetText ;# Constrained scrolling module set widgetText($t,geo) {} global TextType ;# Text bindings module set TextType($t) text } proc Widget_Text {frame height args} { # Create the text widget used to display messages global exwin if ![info exists exwin(scrollbarSide)] { set side right } else { set side $exwin(scrollbarSide) } if ![info exists exwin(hscrollbarSide)] { set hside none } else { set hside $exwin(hscrollbarSide) } if { $hside == "none" } { set cmd [list text $frame.t -relief raised -bd 2 \ -yscroll [list WidgetScrollSet $frame.sv $frame.t]] } else { set cmd [list text $frame.t -relief raised -bd 2 \ -yscroll [list WidgetScrollSet $frame.sv $frame.t] \ -xscroll [list WidgetScrollSet $frame.sh $frame.t]] } if [catch [concat $cmd $args] t] { puts stderr "Widget_Text (warning) $t" set t [eval $cmd $args {-font fixed}] } if {[option get $frame.t width Width] == {}} { $frame.t configure -width 80 } if {[option get $frame.t height Height] == {}} { $frame.t configure -height $height } scrollbar $frame.sv -command [list WidgetTextYview $t] if { $hside != "none" } { scrollbar $frame.sh -command "$frame.t xview" -orient horizontal pack append $frame $frame.sv [list $side filly] \ $frame.sh [list $hside fillx] $t {expand fill} } else { pack append $frame $frame.sv [list $side filly] $t {expand fill} } $t mark set insert 0.0 Widget_TextInitText $t ;# Init state variables if [regexp {setgrid} $args] { wm minsize [winfo toplevel $frame] 10 1 } return $t } proc Widget_TextPageOrNext {t {implied implied}} { global widgetText set next 0 set bottom [lindex [$t yview] 1] set next [expr $bottom >= 1] if {$next && $widgetText(autoNext) } { Ftoc_NextImplied show $implied } else { Widget_TextPageDown $t } } proc Widget_TextPageDown {t} { global widgetText WidgetTextYview $t scroll 1 pages $t mark set insert @1,1 } proc Widget_TextPageUp {t} { global widgetText WidgetTextYview $t scroll -1 pages $t mark set insert @1,1 } proc Widget_TextLineDown {t} { global widgetText $t yview scroll 1 units } proc Widget_TextLineUp {t} { global widgetText $t yview scroll -1 units } proc Widget_TextTop {t} { $t see 1.0 } proc Widget_TextBottom {t} { $t see end } proc WidgetTextYview4.0 {w args} { global widgetText set dir [lindex $args 1] set op [lindex $args 0] set units [lindex $args 2] set view [$w yview] set next [expr 1 - [lindex $view 1]] set prev [lindex $view 0] set span [expr 1. - $next - $prev] if {!$widgetText(smoothScroll) || ($op != "scroll") || ($units != "pages") || ($dir > 0 && $next >= $span) || ($dir < 0 && $prev >= $span)} { eval $w yview $args } else { while {($dir > 0 && $next > 0) || ($dir < 0 && $prev > 0)} { $w yview scroll [expr ($dir > 0) ? 2 : -2] unit update idletasks set view [$w yview] set next [expr 1 - [lindex $view 1]] set prev [lindex $view 0] } } } proc WidgetTextYview {t args} { global widgetText return [eval WidgetTextYview4.0 $t $args] if {!$widgetText(constrained) && !($widgetText(constrainFtoc) && [string match *.ftoc.* $t])} { eval {$t yview} $args return } set mark $args if {([llength $args] == 1) && ([scan $args %d line] == 1)} { if {[string compare $line $args] == 0} { # Being invoked as a scrollcommand, in which lines are # counted from 0. incr to get back to mark coordinates. incr line set mark $line.0 } } if {[lindex $args 0] == "-pickplace"} { set pick -pickplace set mark [lrange $args 1 end] } else { set pick {} } if [$t compare $mark > end] { set mark end } eval {$t yview} $pick {$mark} set height [lindex [split [winfo geometry $t] +x] 1] set bot [$t index @0,$height] set end [$t index end] if {$bot != $end} { return } set max [lindex [$t config -height] 4] set i 0 while {$bot == $end} { set mark [$t index [list $mark -1 lines]] $t yview $mark set bot [$t index @0,$height] incr i if {$i > $max} { return ;# message smaller than window } } set mark [$t index [list $mark +1 lines]] $t yview $mark } proc WidgetScrollSet {s t args} { global widgetText set widgetText($t,view) $args if {$s != {}} { if [catch {eval {$s set} $args} err] { Exmh_Debug WidgetScrollSet $err } } } proc WidgetTextMark {t y} { global widgetText # Exmh_Debug WidgetTextMark $t $y set widgetText($t,mark) $y ;# Remember mark point scan [$t index @1,1] %d widgetText($t,top) ;# and starting top line } proc WidgetTextDragto {t y speed} { global widgetText if ![info exists widgetText($t,mark)] { return } if {$y == $widgetText($t,mark)} { return } # Exmh_Debug WidgetTextDragto $t $y set gridy [WidgetTextGridY $t] set dy [expr {($widgetText($t,mark)-$y)*$speed}] set dlines [expr $dy/$gridy] set rem [expr $dy%$gridy] if {$dy < 0} { incr dlines set rem [expr $rem-$gridy] } if {$dlines >= 1.0 || $dlines <= -1.0} { set widgetText($t,mark) [expr $y+$rem] set newtopline [expr $widgetText($t,top)+$dlines] WidgetTextYview $t $newtopline.0 set widgetText($t,top) $newtopline } } proc WidgetTextGridY {t} { global widgetText set geo [split [winfo geometry $t] +x] if ![info exists widgetText($t,geo)] { set widgetText($t,geo) 0 } if { [string compare $geo $widgetText($t,geo)] != 0 } { # Reverse engineer grid size - broken for windows that get resized. set widgetText($t,geo) $geo set h [lindex $geo 1] set nlines [lindex [$t config -height] 4] set widgetText($t,gridY) [expr $h/$nlines] Exmh_Debug widgetText($t,gridY) $widgetText($t,gridY) } return $widgetText($t,gridY) } proc WidgetTextSelBegin {w x y how} { WidgetTextSelStart $w @$x,$y $how } proc WidgetTextSelStart {w mark how} { global widgetText set widgetText($w,extend) 0 switch -- $how { char {Text_SetInsert $w $mark} word {Text_WordSelect $w $mark} line {Text_LineSelect $w $mark} } } proc WidgetTextSelAgain {w x y} { global widgetText set widgetText($w,extend) 0 tk_textResetAnchor $w @$x,$y Text_SelectTo $w @$x,$y } proc WidgetTextSelMotion {w x y} { global widgetText if ![info exists widgetText($w,extend)] { return } set active $widgetText($w,extend) set h [winfo height $w] if {$y > $h} { set widgetText($w,extend) [expr $y-$h] } else { if {$y < 0} { set widgetText($w,extend) $y } else { set widgetText($w,extend) 0 } } if {$widgetText($w,extend) == 0} { Text_SelectTo $w @$x,$y } else { if {! $active} { set widgetText($w,lastmark) [$w index @$x,$y] after $widgetText(selectDelay) [list WidgetTextSelExtend $w] } } } proc WidgetTextSelExtend {w} { global widgetText if {![info exists widgetText($w,extend)] || ($widgetText($w,extend) == 0)} { return } set delta [expr {$widgetText($w,extend) / 16}] if {$delta == 0} { set delta [expr { ($widgetText($w,extend) < 0) ? -1 : 1 }] } set sign [expr {($delta > 0) ? "+" : ""}] catch { if [$w compare $widgetText($w,lastmark) <= sel.first] { set mark "sel.first $sign $delta lines" } else { set mark "sel.last $sign $delta lines" } set widgetText($w,lastmark) [$w index $mark] Text_SelectTo $w $mark $w yview -pickplace $mark after $widgetText(selectDelay) [list WidgetTextSelExtend $w] } } proc WidgetTextSelDone {w} { global widgetText catch {unset widgetText($w,extend)} Text_SelectionEnd $w 1 } proc Widget_TextEnd {w} { scan [$w index end] %d i incr i -2 } proc tk_textResetAnchor {args} { eval tkTextResetAnchor $args } # Fill out the text widget with enough blanks to allow the # given line to appear at the top. proc Widget_TextPad {w top} { # Assume -height is ok, even though can be wrong after resize # set height [$w cget -height] # # The above replaced by the following, thanks to # Harvey Thompson and # John Haxby # Add newlines so that text in all window set limit 100 while {[$w bbox "end -1c"] != ""} { $w insert end \n if {[incr limit -1] < 0} { break } } # Compute height even if using different fonts set height [expr int([$w index @0,65535]) - int([$w index @0,0]) + 1] set last [$w index "end -1c"] Exmh_Debug Widget_TextPad h=$height last=$last top=$top for {} {$last - $top < $height+1} {set last [expr $last + 1.0]} { $w insert end \n } } exmh-2.9.0/lib/mime.types0000644000170700017070000000467613201227060014606 0ustar valdisvaldis# This is a comment. I love comments. application/activemessage application/andrew-inset application/applefile application/atomicmail application/dca-rft application/dec-dx application/mac-binhex40 hqx application/mac-compactpro cpt application/macwriteii application/msword doc application/msexcel xls application/news-message-id application/news-transmission application/octet-stream bin dms lha lzh exe class tgz taz application/oda oda application/pdf pdf application/postscript ai eps ps application/powerpoint ppt pps application/remote-printing application/rtf rtf application/slate application/wita application/wordperfect5.1 application/x-bcpio bcpio application/x-cdlink vcd application/x-compress Z application/x-cpio cpio application/x-csh csh application/x-director dcr dir dxr application/x-dvi dvi application/x-gtar gtar application/x-gzip gz application/x-hdf hdf application/x-httpd-cgi cgi application/x-koan skp skd skt skm application/x-latex latex application/x-mif mif application/x-netcdf nc cdf application/x-patch patch application/x-sh sh application/x-shar shar application/x-stuffit sit application/x-sv4cpio sv4cpio application/x-sv4crc sv4crc application/x-tar tar application/x-tcl tcl application/x-tex tex application/x-texinfo texinfo texi application/x-troff t tr roff application/x-troff-man man application/x-troff-me me application/x-troff-ms ms application/x-ustar ustar application/x-wais-source src application/zip zip audio/basic au snd audio/mpeg mpga mp2 audio/x-aiff aif aiff aifc audio/x-pn-realaudio ram audio/x-pn-realaudio-plugin rpm audio/x-realaudio ra audio/x-wav wav chemical/x-pdb pdb xyz image/gif gif image/ief ief image/jpeg jpeg jpg jpe image/png png image/tiff tiff tif image/x-cmu-raster ras image/x-portable-anymap pnm image/x-portable-bitmap pbm image/x-portable-graymap pgm image/x-portable-pixmap ppm image/x-rgb rgb image/x-xbitmap xbm image/x-xpixmap xpm image/x-xwindowdump xwd message/external-body message/news message/partial message/rfc822 multipart/alternative multipart/appledouble multipart/digest multipart/mixed multipart/parallel text/html html htm text/plain txt text/richtext rtx text/tab-separated-values tsv text/x-setext etx text/x-sgml sgml sgm text/calendar ics ifb video/mpeg mpeg mpg mpe video/quicktime qt mov video/x-msvideo avi video/x-sgi-movie movie x-conference/x-cooltalk ice x-world/x-vrml wrl vrml exmh-2.9.0/lib/import.tcl0000644000170700017070000001146313201227060014577 0ustar valdisvaldis# import.tcl # # Import folders from other mail tools. # # Copyright (c) 1994 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. proc Import_Init {} { } proc Import_Dialog {} { global _import set w .import if [Exwin_Toplevel $w "Import Tool" Import nobuttons] { set f [Widget_Frame $w name Rim {top expand fill} -bd 10] set _import(win,msg) [Widget_Message $f msg -width 250] set f [Widget_Frame $f rim Rim {top expand fill} -bd 2 -relief raised] Widget_Label $f label {left} -text "Mail Directory:" set _import(win,entry) [Widget_Entry $f name {right fillx expand} -relief sunken] Widget_BindEntryCmd $_import(win,entry) [list ImportWhat $w] set f [Widget_Frame $w but Rim {top fill expand} -bd 10] Widget_AddBut $f cancel "Cancel" "destroy $w" {left filly} set _import(win,okbut) [Widget_AddBut $f ok "OK" [list ImportWhat $w] {right filly}] } catch {destroy .import.folders} $_import(win,msg) config -text \ "Import ucb-mailbox files into MH format. Enter mail directory and click OK." focus $_import(win,entry) } proc ImportWhat { w } { global _import mhProfile set dir [string trim [$_import(win,entry) get]] if {[string length $dir] == 0} { Exmh_Status "Not a directory: $dir" $_import(win,msg) config -text \ "Please enter a mail directory and click OK." return } set dir [glob -nocomplain $dir] if ![file isdirectory $dir] { Exmh_Status "Not a directory: $dir" $_import(win,msg) config -text \ "Not a directory: $dir Enter valid mail directory and click OK." } elseif {[string compare $dir $mhProfile(path)] == 0} { $_import(win,msg) config -text \ "$dir clashes with default MH setting. You must quit exmh and change the Path: setting in your ~/.mh_profile file to a new directory." } else { $_import(win,msg) config -text \ "(Un)Select folders to import and click Import. You'll have to remove the old mail folders manually later." set folders {} set maxl 0 global _importlist catch {unset _importlist} foreach f [glob -nocomplain $dir/*] { if [file isfile $f] { set tail [file tail $f] lappend folders $tail if {[string length $tail] > $maxl} { set maxl [string length $tail] } } } set col 3 set nframes [expr [llength $folders] / $col] for {set i 0} {$i <= $nframes} {incr i} { catch {destroy $w.but$i} set f [Widget_Frame $w but$i] for {set j 0} {$j < $col} {incr j} { set next [lindex $folders 0] if {[string length $next] == 0} { break } set folders [lreplace $folders 0 0] set b [Widget_CheckBut $f j$j $next _importlist($next) {right expand filly}] $b config -onvalue $dir/$next -offvalue {} -width $maxl -anchor w set _importlist($next) $dir/$next } } $_import(win,okbut) config -text Import -command ImportIt set f [winfo parent $_import(win,okbut)] catch {destroy $f.clear} Widget_AddBut $f clear "Unselect All" [list ImportUnselectAll $f.clear] } } proc ImportUnselectAll {button} { global _importlist foreach f [array names _importlist] { set _importlist($f) {} } $button config -text "Select All" -command [list ImportSelectAll $button] } proc ImportSelectAll {button} { global _importlist _import set dir [glob -nocomplain [$_import(win,entry) get]] foreach f [array names _importlist] { set _importlist($f) $dir/$f } $button config -text "Unselect All" -command [list ImportUnselectAll $button] } proc ImportIt {} { global _importlist set t [Help Import "Log of Import Actions"] $t config -state normal -height 20 $t tag configure fixed -font fixed foreach name [lsort [array names _importlist]] { set f $_importlist($name) if {[string length $f] != 0} { global import if [catch {glob $f} file] { Exmh_Status $file continue } Exmh_Status "inc +$name -file $file -notruncate" $t insert end "inc +$name -file $file -notruncate" fixed update idletasks if [catch { set in [open "|inc +$name -file $file -notruncate < /dev/null"] fileevent $in readable [list ImportRead $in $t $name] } result] { $t insert end $result catch {close $in} } $t see end tkwait variable import($name) } } $t config -state disabled Flist_Refresh destroy .import } proc ImportRead {in t name} { global import if [eof $in] { catch {close $in} set import($name) complete return } if [catch {gets $in line} err] { $t insert end $err\n set import($name) complete catch {close $in} } $t insert end $line\n } exmh-2.9.0/lib/seditQP.tcl0000644000170700017070000001216113201227060014632 0ustar valdisvaldis# seditQP # # Crude quoted-printable support for sedit # # Copyright (c) 1994 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. proc SeditInitMimeType { draft t } { # This is really lame. # The code from mime.tcl needs to be generalized so it can # reparse draft files. global sedit exmh set id $sedit($t,id) if {$exmh($id,action) == "dist"} { return } $t mark set cursor insert for {set i 1} {1} {incr i} { set line [$t get $i.0 $i.end] set len [string length $line] if [regexp -nocase {content-type:(.*)$} $line match type] { return } if {$len == 0 || [regexp ^-- $line]} { break } } SeditMsg $t "MIME type text/plain ; charset=$sedit(charset)" SeditMimeType text/plain promote $t mark set insert cursor } proc SeditFixupEncoding { draft t quote } { if [catch {open $draft} in] { SeditMsg $t $out error "Cannot read draft to quote it" } global mime if [catch {open $draft.new w} out] { close $in SeditMsg $t $out error "Cannot fix encoding: $out" } if {$quote} { SeditMsg $t "Quoting text" Exmh_Debug Quoting text } else { SeditMsg $t "8-bit encoding" Exmh_Debug 8-bit encoding } set state header set done 0 set needCoder 0 set type text set typeActive 0 set boundaries {} for {set len [gets $in line]} {$len >= 0} {set len [gets $in line]} { if {$state == "header"} { if [regexp -nocase content-transfer-encoding $line] { Exmh_Debug coding already done set done 1 } if {[regexp "^\[ \t]" $line] && $typeActive} { append type $line } if [regexp -nocase {content-type:(.*)$} $line match type] { set typeActive 1 } else { set typeActive 0 } if {$len == 0 || [regexp ^-- $line]} { set state body set params [split $type \;] set type [string tolower [string trim [lindex $params 0]]] Exmh_Debug type $type foreach sub [lrange $params 1 end] { if [regexp {([^=]+)=(.+)} $sub match key val] { set key [string trim [string tolower $key]] set val [string trim $val \ \"] if {[string compare $key boundary] == 0} { # push new boundary onto the stack set boundaries [linsert $boundaries 0 $val] } } } if {! $done && [regexp -nocase text $type]} { set needCoder 1 Exmh_Debug needCoder $type } } if {$needCoder} { set savedLine $line } else { if {$quote} { puts $out [SeditQuoteHeader $line] } else { puts $out $line } } } else { foreach b $boundaries { if [regexp ^--$b\(--\)?\$ $line match alldone] { catch {unset do_qp} set type text if {[string compare $alldone --] == 0} { # should pop boundary stack set done 1 } else { set state header set typeActive 0 set type text set done 0 } set needCoder 0 Exmh_Debug no coder $line } } if {$needCoder} { set needCoder 0 Exmh_Debug coding if {$quote} { puts $out "Content-Transfer-Encoding: quoted-printable" set do_qp 1 } else { puts $out "Content-Transfer-Encoding: 8bit" } puts $out $savedLine flush $out } if [info exists do_qp] { # don't bother with mime(encode) line-at-a-time puts $out [mime::qp_encode $line] } else { puts $out $line } } } close $out close $in Mh_Rename $draft.new $draft } proc SeditQuoteHeader { line } { global sedit set newline {} set begin 1 if [regexp {^([ ]+)(.*)} $line match space value] { set newline $space set line $value } elseif [regexp {^([^: ]+:[ ]*)(.*)} $line match key value] { set newline $key set line $value } set hithit 0 while {[string length $line] > 0} { if [regexp -indices {^([^][\(\)<>@,;:"/\?\.= ]*)([][\(\)<>@,;:"/\?\.= ]*)} $line match word special] { set x [expr [lindex $special 1]+1] set word [eval {string range $line} $word] set special [eval {string range $line} $special] if {[string length $special] == 0} { set line {} } else { set line [string range $line $x end] } set hit 0 foreach char [split $word {}] { scan $char %c code if {$code > 127} { set hit 1 Exmh_Debug Hit $code $char break } } if {! $hit} { set hithit 0 append newline $word $special } else { append newline =?$sedit(charset)?Q? if {$hithit} { append newline _ } foreach char [split $word {}] { scan $char %c code if {$code > 127 || $char == "_" || $char == "=" || $char == {?}} { append newline [format =%X $code] } else { append newline $char } } append newline ?= $special set hithit 1 } } else { Exmh_Debug Fail <$line> append newline $line set line {} } } return $newline } exmh-2.9.0/lib/ispell.tcl0000644000170700017070000007142713201227060014563 0ustar valdisvaldis################################################################################# # TCL Interactive Spell Checker Version 1.01 # Developed for use in EXMH by John McLaughlin (johnmcl@sr.hp.com) 6/7/97 # # This new spell checking code for EXMH was developed out of # frustration with the current spell checking EXMH code # mostly I could not get it to work the way I wanted it to. # Because I couldn't get the spell checker to work as well # as I would like, I found myself spending inordinate amounts # of time when writing e-mail, constantly fretting over # the spelling. This little piece of code is the result # and seems to work pretty well in my environment. I have # tested this under both linux (redhat 4.0) HPUX 9.05 # # This software operates in one of two different # modes, it can either spell check as you type, marking words # in a variety of ways (underline, bold, italic, etc) that are # not spelled correctly. Also it can put a button in the sedit # window to allow in place spell checking. (The button option # requires changes to your .exmh-defaults file) # # This code depends on the excellent 'ispell' program and most # of the variables & procedure's get their name from it. # This code was developed under ispell v3.1.20 # ####################################################################### # INSTALLATION # to Use: 3 easy steps (Note: EXMH should not be running when you do this) # # Note 2: This may be incorporated into a 'core' EXMH release in # the future so below may not be required..... # # 1) add to the file ~/.tk/exmh/user.tcl in the function 'User_Init' # a call to ispell_Preferences. If you don't have a user.tcl # get one, Usually it can be found in '/usr/local/exmh-' # where is the version of exmh you are running # # if you are really desperate for a user.tcl the following # should work (just make a file called user.tcl with the # following line..... # proc User_Init {} { ispell_Preferences } # # # 2) add the following to your .exmh-defaults at the TOP of the file # # *Sedit.Menubar.ubuttonlist: ispell # *Sedit.Menubar.ispell.text: Ispell # *Sedit.Menubar.ispell.command: Ispell_CheckEntireWindow $t # # 3) in your ~/.tk/exmh directory type 'wish' then type # auto_mkindex . *.tcl # then type 'exit' # # # That should be it! There should be a preferences menu for 'I-Spell' now to allow # control of various parts of the ispell package... Also the 'Sedit' window should # have a 'ispell' button to check the entire document... # if a word is marked misspelled right click on it to add to dictionary or # select an alternate version # ############## Trouble Shooting ###################### # # Did you make sure that.... # Ispell was turned on? (from preferences/I-spell menu) # A 'Miss-Spelled word style' is selected? (from preferences/I-spell) # the User Library directory is ~/.tk/exmh (preferences/Hacking Support) # the changes above were made with EXMH NOT running? # # You are using the correct version of ispell? it works against ispell # version 3.0 & 3.1, version 4.0 (which seems to be a sort of 'non product' # is reported NOT to work. most un*x users seem to have 3.1 installed.. # ############## Performance ########################## # # This spell checker seems to operate without any # obvious performance drag when typing in sedit # with enough ram, most modern workstations should # be able to use this without any obvious performance hit # I find running it under Linux with a 40mb P90 # quite comfortable # as a few benchmarks, this software can spell check # a 2700 word letter in 12 seconds on a P90 running # linux (redhat 4.0) with 40mb of ram. other # timing results indicate a user can expect # a 1.3ms to 3.0ms additional delay for # correctly spelled words, and up to 30ms # for words not spelled correctly. As always # ram helps, ram starved machines will # not fair as well ###################################################### # # Enjoy, if you find it useful or have any comments # please let me know (johnmcl@sr.hp.com) also if you # make any improvements please send them to me # # John McLaughlin, HP Santa Rosa, January 1997 (johnmcl@sr.hp.com) ###################################################### ######################################################### # ispell_init is called to start the entire process off ######################################################### proc Ispell_Init { } { global ispellVars if {! [ info exists ispellVars(currentLanguage) ] } { set ispellVars(currentLanguage) "" } if { $ispellVars(currentLanguage) == $ispellVars(language) } return ; set ispellVars(currentLanguage) $ispellVars(language) ; # mark current language # These things are now specified by the 'Preferences' menu # a good choice f0or the spell command is "ispell -a" # set ispellVars(last_word) "dummy" # this variable are the alternate spellings of the misspelled word... set ispellVars(choices) "" # how to view, see the text.n man page for other ideas # options include -background -foreground # -font etc.. # set ispellVars(viewStyle) "-underline t" if { [ info exists ispellVars(spell_buffer) ] } { if { [catch { close $ispellVars(spell_buffer) } reason] } { Exmh_Debug Ispell Buffer Closed:$reason } } if {!$ispellVars(on)} { set ispellVars(currentLanguage) "disabled" } if {$ispellVars(currentLanguage) == "disabled"} { catch {unset ispellVars(spell_buffer) } return ; } if {[info exists ispellVars(command)]} { set cmd $ispellVars(command) } else { set cmd $ispellVars(defaultCommand) } if [catch {open "|$cmd" r+} ispellVars(spell_buffer)] { set ispellVars(on) 0 ;# triggers trace return } # Poke the process because: # 4.0 doesn't respond with a full line, so gets hangs # 2.0 doesn't output a version number. # We only like 3.* puts $ispellVars(spell_buffer) "?" flush $ispellVars(spell_buffer) gets $ispellVars(spell_buffer) line set version {"unknown"} if {([string compare $line *] == 0) || ([regexp {[Vv]ersion ([0-9])\.} $line x version] && $version != 3)} { # Oh No! Why are you not running version 3.X??? # specifically version 4.0 doesn't work!!! Exmh_Status "Ignoring ispell version $version (3.* required)" catch { close $ispellVars(spell_buffer) } reason set ispellVars(on) 0 return } # # Since this is the right version, we need to read the (blank) reply to # the "?" we sent... # gets $ispellVars(spell_buffer) line IspellWriteSpellBuffer "!" ; # enter terse mode } ###################### # preferences ###################### proc Ispell_Preferences {} { Preferences_Add "I-Spell" \ "This is a module to allow interactive spell checking within a sedit window. It's many fine features include suggested correction and the ability to add new words to a session or to your personal dictionary. For words that are either not correct or not generated by a combination of roots or compounds, the word is marked as not spelled correctly. Please note that the I-Spell module is only active if you select the option \"interactive\" as Spell program (Simple Editor preferences). " { { ispellVars(ReCheckAfterAdd) ispellRecheckAfterAdd ON {Re-Verify after Adds?} "Check this box if you want to re spell check words currently marked as misspelled after you add to the dictionary or session. In general this is a good idea except for extremely long documents where a small delay may be noticed after you add words to your personal dictionary. Additionally the right mouse button can be used to accept suggested words." } { ispellVars(textOnly) ispellTextOnly OFF {Spell Check 'Text' only?} "Check this box if you want to only perform spell checking of the text marked as 'text'. This should avoid spell checking To:, CC: & X-Face: lines. It comes at a small time penalty, turn it off if you want to see a small improvement in response time. Note that turning this option on will also not spell check 'attachments' unless they are marked as Content-Type: text/enriched or text/plain. If you find that spell checking STOPS working in a section of the document you may want to turn this off." } { ispellVars(defaultCommand) ispellCommand "ispell -a -S" {Default speller invocation} "This is the program used to actually do the real work 'ispell -a' is probably a good choice. if you want to use an alternate dictionary, 'ispell -a -d ' may be appropriate. You may find that -S sorts the list of possible words better, see the ispell(1) man page for more details." } { ispellVars(otherCommands) ispellOthers " German { ispell -a -d deutsch } \ French { ispell -a -d francais } English { ispell -a -d english } " { Other Invocations } "Alternate Invocations of the 'Ispell' programs, mostly intended for our friends in Europe who have to work in a variety of languages. This entry must be in label/invocation pairs." } { ispellVars(popupBinding) ispellPopupBinding "ButtonPress-3" {Menu popup bound to:} " A popup window is used for interactive correction of the word under the mouse pointer. This option controls how the popup window is invoked. Any TK bind() event specification that involves the mouse is allowed. Some examples: ButtonPress-3 ButtonPress-2 ButtonPress-1 Shift-3 Control-3 Meta-2 Alt-1" } { ispellVars(viewStyle) ispellStyle {CHOICE underline italic bold bgcolor fgcolor other } {Misspelled word style} "This is how to display misspelled words. Use the built in types or create your own using 'other'. Colors are given as X11 color names or #RGB. Some examples for the 'other' style (see the TK docs for more info): -underline t -background red -foreground Bisque -font -font *italic* -font *bold* -relief -fgstipple -bgstipple Bitmaps can be many things, 'gray50' and 'gray25' are popular. Effects can also be combined: -underline t -foreground red -bgstipple gray25 -color red" } { ispellVars(viewStyle-Color) ispellStyleColor red {color:} "color for fgcolor and bgcolor" } { ispellVars(viewStyle-Other) ispellStyleOther {-underline t -foreground red} {other:} "Style if 'other' is selected" } } global ispellVars set ispellVars(language) default trace variable ispellVars(on) w IspellOnOff } proc IspellOnOff {args} { global ispellVars catch {unset ispellVars(currentLanguage)} Ispell_Init } # a safe procedure to write to the ispell buffer # this procedure dumps the variable 'word' to the spell buffer # if the buffer has died, it will restart it proc IspellWriteSpellBuffer { word } { global ispellVars if {$ispellVars(currentLanguage) == "disabled"} { return * } ; puts $ispellVars(spell_buffer) $word if { [ catch { flush $ispellVars(spell_buffer) } ] } { Exmh_Debug "Ispell process terminated!!!!!, temp disabling" set ispellVars(language) disabled Ispell_Init return "*" ; # return if we had to restart } } # This procedure kills the ispell buffer # proc Ispell_Kill {} { global ispellVars close $ispellVars(spell_buffer) set ispellVars(on) 0 } ########################################## # this is the proc that does the # actual spell checking, it will return a # '*' if everything is cool, otherwise # it returns a list of possible miss-spelled # words. See ispell(1) for more details proc IspellWords line { global ispellVars regsub -all { +} $line { } line ;# compress out extra spaces set count [llength [split $line { }]] ;# Count space separated words set result "" if { $ispellVars(currentLanguage) == "disabled" } { return "*" } ; # clear out the fileevent if { [ catch {fileevent $ispellVars(spell_buffer) readable {} } ] } { Ispell_Init return "*" } # so the puts stuff doesn't freak out # CRITCAL prepend a '^' to keep the buffer from freaking puts $ispellVars(spell_buffer) "^$line" # we have to put the ^ in front of the line so ispell works correctly # see ispell(1) for more details if { [ catch { flush $ispellVars(spell_buffer) } ] } { Exmh_Debug "Ispell process terminated!!!!!, restarting" Ispell_Init return "*" ; # return if we had to restart } # loop through list of words, usually there is just 1 for { set i 0 } { $i <= $count } { incr i } { gets $ispellVars(spell_buffer) var if {$var == {} } then { lappend result "*"; break; } lappend result $var } # invoke a fileevent to help flush out the data so wer are always in sync fileevent $ispellVars(spell_buffer) readable { global ispellVars gets $ispellVars(spell_buffer) dummy } return $result } # this proc spell checks the word under the current cursor # marking it with a 'MissSpelled' tag if it is in fact incorrect # text is the text window # This version runs about 300us slower than the previous # version using tk's built in 'wordstart' and 'wordend' # (1.3ms vs 1.7ms) proc IspellTextWindow { text } { ################# # WARNING # CHANGES FOR SUPPORT OF EUROPEAN CHARACTERS!! ########################## set start [ $text get "insert linestart" insert ] set end [ $text get insert "insert lineend" ] set e1 "" set s1 "" regexp "\[^\t \]*" $end e1 set e1 [ string trim $e1 ] regexp "\[^\t \]+$" $start s1 set startIndex "insert - [string length $s1] chars" set stopIndex "insert + [string length $e1] chars " set word "[ string trim $s1$e1 "\"\{\}\[\] \t" ] " IspellMarkWord $text $startIndex $stopIndex $word } # this Proc is to spell check words that with 'inserts' # i.e. after 'space', 'tab' etc.... This version # runs at exactly the same speed as the tk built # in version (1.3ms) so I feel pretty comfortable # that this shouldn't effect speed too much # all test times were gotten via 'time' # and thus may have some errors (especially # with regexps, I think the system compiles # them). In this version I can't use # tk's built in 'word' functions because # they don't allow for european characters.... proc IspellTextWindowInsert { text } { ################# # WARNING # CHANGES FOR SUPPORT OF EUROPEAN CHARACTERS!! ########################## set start [ $text get "insert linestart" insert ] set s1 "" # now let's pick off the last word regexp "\[^\t ]+$" $start s1 set startIndex "insert - [string length $s1] chars" set stopIndex "insert" set word " [ string trim $s1 "\"\{\}\[\] \t" ] " IspellMarkWord $text $startIndex $stopIndex $word } #################################################### # proc to mark words in the text window, with the given # indexes, the 'word' is the word in question #################################################### proc IspellMarkWord {text startIndex stopIndex word} { global ispellVars ; #first let's not mark the word bad if we aren't in a section marked 'type=text*" if {$ispellVars(textOnly)} { if { ! [ string match "*type=text*" [ $text tag names insert ] ] } { return * } ; } set result [ IspellWords $word ]; # * means fine, + means a root?, - means compount controlled by -C option of ispell if { ! [regexp {^[*+-]} $result ] } { $text tag add MissSpelled $startIndex $stopIndex set prompt "Suggested for $word: [ lreplace [ lindex $result 0 ] 0 3 ]" # EXMH Specific SeditMsg $text $prompt } else { $text tag remove MissSpelled $startIndex "$stopIndex +1c" } set ispellVars(last_word) $word ; # store word so we don't re-check next # time return $result } ############################################################## # Proedure to call to mark words after the dictionary has been # modified, called from within the 'add' menus..... # ############################################################## proc IspellReCheckBuffer { window startIndex stopIndex word } { global ispellVars; # first let's make sure it's a real word.... if { $word == "" } return ; IspellMarkWord $window $startIndex $stopIndex $word; # check word requested if { [ info exists ispellVars(ReCheckAfterAdd) ] } { if { $ispellVars(ReCheckAfterAdd) } { IspellReCheckWords $window ; # re-check buffer if requested.. } } } ########################################################## # This proc will take the word currently under the mouse pointer # spell check it, and pop up a menu with suggestions or allowing # additions to the ispell-dictionary # 'text' is the text window, x,y are the co-ordinates relative to the # window, X,Y are the co-ordinates relative to the root window ########################################################## proc IspellPostMenuChoices { text x y X Y } { global ispellVars; set adjustment {} set oldInsert [ $text index insert ] $text mark set insert "@$x,$y" set start [ $text get "insert linestart" insert ] set end [ $text get insert "insert lineend" ] set e1 "" set s1 "" regexp "\[^\t \]*" $end e1 set e1 [ string trim $e1 ] regexp "\[^\t \]+$" $start s1 set startIndex "insert - [string length $s1] chars" set stopIndex "insert + [string length $e1] chars " set word $s1$e1 set word [ string trim $word "\]\[\.\,\<\>\/\?\!\@\#\%\*0123456789\&\@\(\)\:\;\$ \{\}\"\\ \'\~\`\_\-\+\t\n\r\b\a\f\v\n "] set word [ string trim $word ] # set stopIndex [ $text index "@$x,$y wordend" ] # set startIndex [ $text index "$stopIndex - 1 chars wordstart" ] # set word " [ string trim [ $text get $startIndex "$stopIndex wordend" ] \ # "\@\(\)\:\;\$ \{\}\"\\ \t\n\r\b\a\f\v\n "] " ; # " # set word [ string trim $word ] ; # get rid of white space # if there is no word to mention, don't even post a menu... if { $word == "" } return ; set result [ IspellMarkWord $text $startIndex $stopIndex $word ] $text mark set insert $oldInsert ; # get it back where it belongs # create a meanu set menu "$text.m" catch { destroy $menu } menu $menu -tearoff f # remember the menu name so we can unpost it later. set ispellVars(PopupMenu) $menu # first let's label the menu with the current language $menu add command -label $ispellVars(language) -state disabled # now if spell checking is disabled, let's mark menus as such set disFlag normal if { $ispellVars(currentLanguage) == "disabled" } { set disFlag "disabled" } $menu add separator $menu add command -label "Add '$word' to Dictionary" -command \ "IspellWriteSpellBuffer \"*$word\";\ IspellWriteSpellBuffer \#;\ IspellReCheckBuffer $text \"$startIndex\" \"$stopIndex\" $word;" -state $disFlag # add word to dictionary, save dictionary, recheck word $menu add command -label "Accept '$word' for this session" -command \ "IspellWriteSpellBuffer \"@$word\";\ IspellReCheckBuffer $text \"$startIndex\" \"$stopIndex\" $word;" -state $disFlag # add word for this session, recheck word $menu add separator foreach i [ split [ lreplace [ lindex $result 0 ] 0 3 ] "," ] { set choice [ string trim $i ", " ] $menu add command -label $choice -command "IspellReplaceWordInText $text $x $y \"$choice\" " } $menu add separator menu $menu.sub -tearoff f $menu.sub add radiobutton -label "disabled" \ -command "set ispellVars(language) disabled ; set ispellVars(command) \"\"; Ispell_Init" -variable ispellVars(language) -value "disabled" $menu.sub add radiobutton -label "default" \ -command "set ispellVars(language) default ; set ispellVars(command) \"$ispellVars(defaultCommand)\"; Ispell_Init" \ -variable ispellVars(language) -value "default" set count [ llength $ispellVars(otherCommands) ] for { set i 0 } { $i < $count } { incr i 2 } { set lab [ lindex $ispellVars(otherCommands) $i ] set command [ lindex $ispellVars(otherCommands) [ expr $i +1 ] ] $menu.sub add radiobutton -label "$lab " \ -command " set ispellVars(language) \"$lab\" ; set ispellVars(command) \"$command\"; Ispell_Init" \ -variable ispellVars(language) -value "$lab" } $menu add cascade -label "Alternate..." -menu $menu.sub tk_popup $menu $X $Y } ####################################################### # # Procedure called to Unpost # the menu ####################################################### proc IspellUnPostMenuChoices {window } { global ispellVars catch { tkMenuUnpost $ispellVars(PopupMenu) } } ######################################################### # This proc will replace whatever word is listed at x,y # with 'word' It goes to some lengths to keep surrouning # punctuation. ######################################################### proc IspellReplaceWordInText { text x y word } { set oldInsert [ $text index insert ] $text mark set insert "@$x,$y" set start [ $text get "insert linestart" insert ] set end [ $text get insert "insert lineend" ] set e1 "" set s1 "" regexp "\[^\t \]*" $end e1 set e1 [ string trim $e1 ] regexp "\[^\t \]+$" $start s1 # If we are being asked to replace a word, first remove the tag # so that whatever highlighting is there will be gone. $text tag remove MissSpelled "insert - [string length $s1] chars" "insert + [string length $e1] chars " # Now let's clean up that string a bit..... remove punctuation & stuff set e1 [ string trim [ string trim $e1 ] "\]\[\.\,\<\>\/\?\!\@\#\%\*0123456789\&\@\(\)\:\;\$ \{\}\"\\ \'\~\`\_\-\+\t\n\r\b\a\f\v\n "] set s1 [ string trim [ string trim $s1 ] "\]\[\.\,\<\>\/\?\!\@\#\%\*0123456789\&\@\(\)\:\;\$ \{\}\"\\ \'\~\`\_\-\+\t\n\r\b\a\f\v\n "] # now let's remove the old word & insert the new word. set startIndex "insert - [string length $s1] chars" set stopIndex "insert + [string length $e1] chars " set startInsert [ $text index $startIndex ] $text delete $startIndex $stopIndex $text insert $startInsert $word $text mark set insert $oldInsert ; # get it back where it belongs } ########################################################## # EXMH Specific procedure to bind the window in question # note that this has to be in the current process # it won't automagically be sucked in # a call to 'IspellPreferences' should do the trick... ########################################################## proc Hook_SeditInit_TagMissSpelled { file window } { global ispellVars sedit # only configure the window for ispell support if it is # actually needed, and if the appropriate variables exist set id [SeditId $file] set b .sedit${id}.but if {$sedit(spell) == "interactive"} { set ispellVars(on) 1 $b.more.m entryconfigure Spell* -state disabled $b.more.m entryconfigure I-Spell* -state normal } else { set ispellVars(on) 0 $b.more.m entryconfigure Spell* -state normal $b.more.m entryconfigure I-Spell* -state disabled return } # bind the window..... # use default style of underline set style "-underline t" if { [ catch { switch -exact -- $ispellVars(viewStyle) \ underline { set style "-underline t"} \ italic { set style "-font *italic*" } \ bold { set style "-font *bold*"} \ other { set style "$ispellVars(viewStyle-Other)" } \ bgcolor { set style "-background $ispellVars(viewStyle-Color)" } \ fgcolor { set style "-foreground $ispellVars(viewStyle-Color)" } eval $window tag configure MissSpelled $style } result ] } { tk_dialog .window "Bad Style" \ "Invalid I-Spell style: '$result' changing to underline" \ {} 0 ok eval $window tag configure MissSpelled -underline t } # Only bind the window if 'ispell' is turned on... # and if so, disable external ispell (and vice-versa) if { $ispellVars(on) == 1 } { set ispellVars($window,effect) 1 Ispellbind $window } set ispellVars(command) $ispellVars(defaultCommand) set ispellVars(language) "default" # Only init the spell checker if it had already not been previously init'd if { ! [ info exists ispellVars(spell_buffer) ] } { Ispell_Init ; # init if the spell buffer is undefine } } # this procedure re-checks the entire buffer in the # window specified by 'window' proc Ispell_CheckEntireWindow { text } { global ispellVars set oldInsert [ $text index insert ] set count 0 # First things first, because this function COULD be called without # using any of the other ispell stuff, first ensure that the ispell # process is running... # Only init the spell checker if it had already not been previously init'd if { ! [ info exists ispellVars(spell_buffer) ] } { Ispell_Init ; # init if the spell buffer is undefine } # Pop up a little window to allow spell checking to be turned off...... # set ispellVars(label) "Stop Spell Checking" catch { destroy .ispellStopWindow } set top [ toplevel .ispellStopWindow ] wm group .ispellStopWindow . button $top.b -textvariable ispellVars(label) -command { set ispellVars(label) "" } label $top.l1 -bitmap warning label $top.l2 -bitmap warning pack $top.l1 -side left pack $top.b -side left pack $top.l2 -side left set endOfDoc [ $text index end ] ; # get the last index mark set current 1.0 # here is the actual code to spell check the document while { [ expr $current < $endOfDoc ] } { if { $ispellVars(label) == "" } { break} $text mark set insert "$current" set start [ $text get "insert linestart" insert ] set end [ $text get insert "insert lineend" ] set e1 "" set s1 "" regexp "\[^\t \]*" $end e1 # set e1 [ string trim $e1 ] regexp "\[^\t \]+$" $start s1 set startIndex "insert - [string length $s1] chars" set stopIndex "insert + [string length $e1] chars " set word "[ string trim $s1$e1 "\"\{\}\[\]" ] " set current [ $text index "$stopIndex + 2 chars" ] if {[string length $word] == 1} continue; # speed up process for small words.... incr count update if { $count > 120 } { $text see $current set count 0 } IspellMarkWord $text $startIndex $stopIndex $word } destroy $top # now let's redisplay the screen at the insert point.... $text mark set insert "$oldInsert" $text see insert } ######################################################## # procedure to re-check bound words to reconfirm they # are still missspelled # note that if quite a few words are missSpelled this could # take quite a while.... Also note that this should probably # only be called AFTER the dictionary has changed/updated ######################################################## proc IspellReCheckWords {window} { global ispellVars set ranges [ $window tag ranges MissSpelled ] set ispellVars(label) "Stop Spell Checking" set wcount 0 if { [ expr [ llength $ranges ] > 100 ] } { # Only pop up a window if # 100 or so need to be re-checked. catch { destroy .ispellStop } toplevel .ispellStop button .ispellStop.b -textvariable ispellVars(label) -command { set ispellVars(label) "" } label .ispellStop.l1 -bitmap warning label .ispellStop.l2 -bitmap warning pack .ispellStop.l1 -side left pack .ispellStop.b -side left pack .ispellStop.l2 -side left } # loop through all the current words marked as misspelled # for { set i 0 } { $i < [ expr [llength $ranges] / 2 ] } { incr i } { set startIndex [ lindex $ranges [ expr $i*2 ] ] set stopIndex [ lindex $ranges [ expr $i*2+1 ] ] if { [ $window compare "$startIndex + 1 chars" == "$stopIndex" ] } { $window tag remove MissSpelled $startIndex "$stopIndex +1c" } set word " [ string trim [ $window get $startIndex $stopIndex ] \ " \t\"\{\}\[\]"] " ; # " if { $ispellVars(label) == "" } { break } incr wcount if { $wcount > 20 } { $window see $startIndex set wcount 0 } update set result [ IspellMarkWord $window $startIndex $stopIndex $word ] } # destroy the toplevel window catch { destroy .ispellStop } # put the window back under the insert cursor $window see insert } # Call this procedure with the text window path to bind the spell command proc Ispellbind { text } { global ispellVars; set command {IspellTextWindow %W} ; bind $text "IspellTextWindowInsert %W" bind $text "IspellTextWindowInsert %W" bind $text "$command" bind $text "$command" bind $text "$command" bind $text "$command" bind $text " $command " # How do we correct words? Normally button-3! bind $text <$ispellVars(popupBinding)> { IspellPostMenuChoices %W %x %y %X %Y } ; # no user configurable way to select the unpost... # tk_popup should unpost the menu for us automatically # bind $text { IspellUnPostMenuChoices %W } } exmh-2.9.0/lib/getnews.tcl0000644000170700017070000002015613201227060014740 0ustar valdisvaldis# # getnews.tcl - NNTP retrieve client for exmh # Needs tcl7.5/tk4.1 or above. # # Chris Keane (Chris.Keane@comlab.ox.ac.uk) # 26-Feb-97 proc GetNews {} { global NNTP if {![llength $NNTP(groups)]} { Exmh_Status "No groups specified to retrieve" return } BgAction "News" GetNewsBg } proc GetNewsBg {} { busy Exmh_Status "Retrieve news: [GetNewsInt]" } proc GetNewsInt {} { global NNTP mhProfile env if {![llength $NNTP(newsrc)]} { set newsrc {~/.newsrc} } else { set newsrc $NNTP(newsrc) } if {[file exists $newsrc]} { if {[catch {open $newsrc} rcfile]} { return "cannot open file $newsrc\n$rcfile" } } else { set rcfile {} } Exmh_Status "Connecting to server $NNTP(host)..." if {[catch {socket $NNTP(host) $NNTP(port)} nntpskt]} { if {[string length $rcfile]} { close $rcfile } return $nntpskt } set line [NNTPReply $nntpskt] if {[string first 200 $line] && [string first 201 $line]} { NNTPClose $nntpskt $rcfile return $line } # Open the .newsrc file and extract the lines relating to the groups # we're going to retrieve set gcount 0 set grps $NNTP(groups) while {[string length $rcfile] && [llength $grps] && [gets $rcfile line] != -1} { if {![regexp {^([0-9A-Za-z+&-\._]+)[:!][ ]*([0-9,-]+)} $line match group articles]} { continue } set indx [lsearch -exact $grps $group] if {$indx != -1} { set thegrps($gcount) $group set thearts($gcount) $articles incr gcount set grps [lreplace $grps $indx $indx] } } # If there are any groups which weren't in the .newsrc file, set their # "articles which have been read" list to {} foreach group $grps { set thegrps($gcount) $group set thearts($gcount) {} incr gcount } # make a temp directory for putting articles in while we work if {![file isdirectory $mhProfile(path)/MyIncTmp]} { file mkdir $mhProfile(path)/MyIncTmp } # Now get the articles from the server set thisg 0 set acount 0 set ecount [file tail [Mh_Path MyIncTmp new]] Exmh_Status "Retrieving articles..." while {$thisg < $gcount} { NNTPCommand $nntpskt "GROUP $thegrps($thisg)" set line [NNTPReply $nntpskt] if ![string first 480 $line] { set ok [NNTPAuthenticate $nntpskt] if $ok { NNTPCommand $nntpskt "GROUP $thegrps($thisg)" set line [NNTPReply $nntpskt] } } if {[string first 211 $line]} { Exmh_Status "Cannot select newsgroup $thegrps($thisg)" Exmh_Debug "GetNews Line: $line" set thearts($thisg) "X" incr thisg continue } if {![regexp {^211 ([0-9]+) ([0-9]+) ([0-9]+)} $line match num first last]} { NNTPClose $nntpskt $rcfile return "cannot parse server response" } if {$num == 0} { incr thisg continue } # start reading at the next unread article in this group if {[regexp {^([0-9]+[,-])*([0-9]+)$} $thearts($thisg) match num tlast] && $tlast >= $first} { set first [expr $tlast + 1] } set line 423 while {![string first 423 $line] || ![string first 430 $line]} { if {$first > $last} { break } NNTPCommand $nntpskt "STAT $first" set line [NNTPReply $nntpskt] if {![string first 223 $line]} { break } if {[string first 423 $line] && [string first 430 $line]} { NNTPClose $nntpskt $rcfile return $line } incr first } # if we get a 423 or 430 back, there were no further articles anyway if {![string first 423 $line] || ![string first 430 $line]} { incr thisg continue } # otherwise we must have got a 223, i.e. the article is selected Exmh_Status "Reading group $thegrps($thisg) (max [expr $last-$first+1] articles)..." while {![string first 223 $line]} { NNTPCommand $nntpskt "ARTICLE" set line [NNTPReply $nntpskt] if {[string first 220 $line]} { NNTPClose $nntpskt $rcfile return "unexpected server response" } if {![regexp {^220 ([0-9]+)} $line match anum]} { NNTPClose $nntpskt $rcfile return "cannot parse server response" } if {[catch {open $mhProfile(path)/MyIncTmp/[expr $ecount+$acount] {WRONLY CREAT EXCL}} afile]} { NNTPClose $nntpskt $rcfile return "cannot write temp article file\n$afile" } set line [gets $nntpskt] while {![regexp {^\.$} $line]} { # two leading .'s should be compressed into one regexp {^\.(\..*)} $line match line puts $afile $line set line [gets $nntpskt] } close $afile NNTPCommand $nntpskt "NEXT" set line [NNTPReply $nntpskt] if {[string first 223 $line] && [string first 421 $line]} { NNTPClose $nntpskt $rcfile return $line } incr acount } # update the article references for the new .newsrc file set thearts($thisg) [AL_Update $thearts($thisg) $anum] incr thisg } if {$acount} { Inc_Presort 0 Exmh_Status "Writing .newsrc file..." if {[string length $rcfile]} { seek $rcfile 0 set oldrc [glob $newsrc] set newsrc $newsrc.exmh } if {[catch {open $newsrc w} nrcfile]} { NNTPClose $nntpskt $rcfile return "cannot write new .newsrc file\n$nrcfile" } # re-parse the old .newsrc file, replacing the relevant article numbers # with their new values set thisg 0 while {[string length $rcfile] && [gets $rcfile line] != -1} { if {$thisg >= $gcount || ![regexp {^([0-9A-Za-z+&-\._]+)([:!][ ]*)([0-9]+[,-])*[0-9]+$} $line match group chaff first] || [string compare $group $thegrps($thisg)]} { puts $nrcfile $line continue } if {[string match X $thearts($thisg)]} { # we didn't manage to select this group puts $nrcfile $line } else { puts $nrcfile "$group$chaff$thearts($thisg)" } incr thisg } while {$thisg < $gcount} { if {![string match X $thearts($thisg)]} { puts $nrcfile "$thegrps($thisg): $thearts($thisg)" } incr thisg } } else { set nrcfile {} } NNTPClose $nntpskt [list $rcfile $nrcfile] if {[string length $rcfile] && [string length $nrcfile] && [catch { file rename -force $oldrc $oldrc.old file rename -force [glob $newsrc] $oldrc } err]} { return "failed to rename .newsrc files\n$err" } return "$acount new articles retrieved" } # parse the existing .newsrc entry and update it with new values proc AL_Update {rcentry next} { # a few different cases here; first, if the existing entry is empty if {![string length $rcentry]} { set rcentry 1 } # if the last part of the existing entry is a single number if {[regexp {^([0-9]+(-[0-9]+)?,)*([0-9]+)$} $rcentry match fst snd last]} { if {$next == $last} { return $rcentry } else { return "$rcentry-$next" } # otherwise the last part of the existing entry must be a range mmm-nnn } else { regexp {^(([0-9]+(-[0-9]+)?,)*[0-9]+-)([0-9]+)$} $rcentry match fst snd thd last if {$next == $last} { # this case shouldn't actually ever happen, but just in case... 8-) return $rcentry } else { return "$fst$next" } } } proc NNTPCommand {nntpskt cmd} { puts $nntpskt $cmd regsub {pass.*$} $cmd {pass *****} cmd Exmh_Debug NNTPCommand: $cmd flush $nntpskt } proc NNTPReply {nntpskt} { set line [gets $nntpskt] Exmh_Debug NNTPReply: $line return $line } proc NNTPClose {nntpskt rcfiles} { global mhProfile puts $nntpskt QUIT close $nntpskt foreach rcf $rcfiles { if {[string length $rcf]} { close $rcf } } File_Delete $mhProfile(path)/MyIncTmp/$mhProfile(mh-sequences) catch {file delete $mhProfile(path)/MyIncTmp} } # # 'Original' AUTHINFO implementation # i.e., not AUTHINFO SIMPLE or AUTHINFO GENERIC # see 'Common NNTP extensions' # proc NNTPAuthenticate {sock} { global NNTP if {$NNTP(user)==""} { tk_messageBox -message {News server requires authentication. Check username and password in NNTP preferences} -type ok return 0 } NNTPCommand $sock "authinfo user $NNTP(user)" set line [NNTPReply $sock] NNTPCommand $sock "authinfo pass $NNTP(pass)" set line [NNTPReply $sock] if [string first 281 $line] { tk_messageBox -message {Authentication to NNTP server failed. Check username and password in NNTP preferences} -type ok return 0 } else { return 1 } } exmh-2.9.0/lib/hourglass1.bitmap0000644000170700017070000000074513201227060016050 0ustar valdisvaldis#define hourglass_width 19 #define hourglass_height 21 static char hourglass_bits[] = { 0xff, 0xff, 0x07, 0x55, 0x55, 0x05, 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01, 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01, 0xc2, 0x0a, 0x03, 0x46, 0x05, 0x01, 0x82, 0x0a, 0x03, 0x06, 0x05, 0x01, 0x02, 0x03, 0x03, 0x86, 0x05, 0x01, 0xc2, 0x0a, 0x03, 0x66, 0x15, 0x01, 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01, 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01, 0xa2, 0x2a, 0x03, 0xff, 0xff, 0x07, 0xab, 0xaa, 0x02}; exmh-2.9.0/lib/seditCompose.tcl0000644000170700017070000000765113201227060015727 0ustar valdisvaldis# seditCompose.tcl # # This routine defines a table that maps from two-character sequences, # which are typed after the Compose key, into 8-bit input characters. # # Copyright (c) 1993 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. proc SeditComposedKey { w a1 a2 } { global composedkey sedit if [info exists composedkey($a1$a2)] { SeditInsert $w "$composedkey($a1$a2)" if {$sedit($w,quote) < 0} { set sedit($w,quote) 1 } } elseif [info exists composedkey($a2$a1)] { SeditInsert $w "$composedkey($a2$a1)" if {$sedit($w,quote) < 0} { set sedit($w,quote) 1 } } else { SeditInsert $w "$a1$a2" } bind SeditText { SeditInsert %W %A } } proc SeditComposedKeyBindings {} { global composedkey set composedkey("a) "\xE4" set composedkey("e) "\xEB" set composedkey("i) "\xEF" set composedkey("u) "\xFC" set composedkey("o) "\xF6" set composedkey("A) "\xC4" set composedkey("E) "\xCB" set composedkey("I) "\xCF" set composedkey("O) "\xD6" set composedkey("U) "\xDC" set composedkey(`a) "\xE0" set composedkey(`e) "\xE8" set composedkey(`i) "\xEC" set composedkey(`u) "\xF9" set composedkey(`o) "\xF2" set composedkey(`A) "\xC0" set composedkey(`E) "\xC8" set composedkey(`I) "\xCC" set composedkey(`O) "\xD2" set composedkey(`U) "\xD9" set composedkey(^a) "\xE2" set composedkey(^e) "\xEA" set composedkey(^i) "\xEE" set composedkey(^u) "\xFB" set composedkey(^o) "\xF4" set composedkey(^A) "\xC2" set composedkey(^E) "\xCA" set composedkey(^I) "\xCE" set composedkey(^O) "\xD4" set composedkey(^U) "\xDB" set composedkey('a) "\xE1" set composedkey('e) "\xE9" set composedkey('i) "\xED" set composedkey('u) "\xFA" set composedkey('o) "\xF3" set composedkey('y) "\xFD" set composedkey('A) "\xC1" set composedkey('E) "\xC9" set composedkey('I) "\xCD" set composedkey('O) "\xD3" set composedkey('U) "\xDA" set composedkey('Y) "\xDD" set composedkey(/o) "\xF8" set composedkey(/O) "\xD8" set composedkey(ae) "\xE6" set composedkey(AE) "\xC6" set composedkey(~a) "\xE3" set composedkey(~o) "\xF5" set composedkey(~n) "\xF1" set composedkey(~A) "\xC3" set composedkey(~O) "\xD5" set composedkey(~N) "\xD1" set composedkey(aa) "\xE5" set composedkey(AA) "\xC5" set composedkey(*a) "\xE5" set composedkey(*A) "\xC5" set composedkey(\"\") "\xA8" set composedkey(,,) "\xB8" set composedkey(!!) "\xA1" set composedkey(??) "\xBF" set composedkey(ss) "\xDF" set composedkey(|c) "\xA2" set composedkey(-l) "\xA3" set composedkey(,c) "\xE7" set composedkey(,C) "\xC7" } proc Sedit_ComposeUI {} { global composedkey if [Exwin_Toplevel .compose "Compose Key" Key] { set f .compose Widget_Message $f msg -aspect 1000 -text \ "Compose Key Sequences Press the Compose key and the two-letter sequence on the left to get the special character in the right-hand column. You can define the Compose key in the Simple Edit dialog. The font used to display these characters is in the status line." set t [Widget_Text $f 20 -width 20] $t config -width 20 foreach family { courier lucidatypwriter lucida times palatino * } { if {[catch {$t config -font -*-$family-medium-r-*-*-12-*-*-*-*-*-iso8859-1}] == 0} { break } } } else { set t .compose.t } Exmh_Status [lindex [$t config -font] 4] $t delete 1.0 end foreach key [lsort [array names composedkey]] { $t insert insert " $key\t$composedkey($key)\n" } } exmh-2.9.0/lib/xns.tcl0000644000170700017070000000166613201227060014101 0ustar valdisvaldis# # xns.tcl # # Thin layer over xnsgetmail routine that fetching messages from # an XNS mail server to your UNIX spool file. An expect script is # used to check if you need to login or not.. # # Copyright (c) 1994 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. proc Xns_GetMail {} { global exmh Exmh_Status "xnsgetmail -k" if [catch {exec $exmh(expect) -f $exmh(library)/xnsgetmail.exp} err] { if [regexp {XNS username} $err] { Exmh_Status "Please XNS login" exec xterm -e xnslogin after 1000 Xns_GetMail } else { Exmh_Status $err } } } exmh-2.9.0/lib/select.tcl0000644000170700017070000001212113201227060014534 0ustar valdisvaldis# select.tcl # # Keystroke bindings to select for message or folder # # Copyright (c) 1993 Xerox Corporation. # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # makes no warranty about the software, its performance or its conformity to # any specification. # Select_Bindings creates bindings on the message and ftoc windows # that in turn warp focus to the Status window for folder & message selection proc Select_Bindings { w } { global select set select(sel) {} set select(prompt) {} foreach digit {0 1 2 3 4 5 6 7 8 9} { bind $w {SelectDigit %W %A} } bind $w {SelectPlus %W} set select(toggle) { Change Target } } proc SelectPlus { w } { global select $select(entry) configure -state normal focus $select(entry) set select(sel) {} set select(prompt) "[lindex $select(toggle) 0] Folder:" set select(folder) 1 Exmh_Status "$select(prompt) " } proc SelectDigit {w digit} { global select $select(entry) configure -state normal focus $select(entry) set select(sel) $digit set select(prompt) Msg: catch {unset select(folder)} Exmh_Status "Select Msg: $select(sel)" Msg_Change $select(sel) noshow } # These are the bindings on the status entry widget proc Select_EntryBind { w } { global select set select(entry) $w bindtags $w [list $w Entry] bind $w {SelectTypein %W %A} bind $w {SelectToggle %W } bind $w {SelectPrev %W } bind $w {SelectComplete %W} bind $w {SelectComplete %W} bind $w {SelectReturn %W} bind $w {SelectReturn %W %A} bind $w {SelectBackSpace %W} bind $w {SelectBackSpace %W} bind $w {SelectBackSpace %W} bind $w {SelectCancel %W} bind $w {SelectCancel %W} bind $w {SelectClear %W} } proc SelectTypein {w {a {}}} { global select if {$a == {}} { return } if [info exists select(match)] { set select(sel) $select(match) unset select(match) catch {unset select(allfolders)} } append select(sel) $a Exmh_Status "$select(prompt) $select(sel)" if ![info exists select(folder)] { catch { Msg_Change $select(sel) noshow } } } proc SelectBackSpace { w } { global select if [info exists select(match)] { set select(sel) $select(match) unset select(match) catch {unset select(allfolders)} } set select(sel) [string range $select(sel) 0 [expr [string length $select(sel)]-2]] Exmh_Status "$select(prompt) $select(sel)" if ![info exists select(folder)] { catch { Msg_Change $select(sel) noshow } } } proc SelectToggle {w} { global select if [info exists select(folder)] { if {$select(sel) != ""} { SelectTypein $w + return } set select(toggle) [list [lindex $select(toggle) 1] [lindex $select(toggle) 0]] set select(prompt) "[lindex $select(toggle) 0] Folder:" } else { catch { if [regexp {^[0-9]+$} $select(sel)] { incr select(sel) } Msg_Change $select(sel) noshow } } Exmh_Status "$select(prompt) $select(sel)" } proc SelectPrev {w} { global select if [info exists select(folder)] { SelectTypein $w "-" } else { catch { if [regexp {^[0-9]+$} $select(sel)] { incr select(sel) -1 } Msg_Change $select(sel) noshow } Exmh_Status "$select(prompt) $select(sel)" } } proc SelectComplete { w } { global select if [info exists select(folder)] { global flist if ![info exists select(allfolders)] { set select(allfolders) $flist(allfolders) } set ix 0 foreach f $select(allfolders) { incr ix if [string match $select(sel)* $f] { set select(allfolders) [lrange $select(allfolders) $ix end] if {$select(allfolders) == {}} { unset select(allfolders) } set select(match) $f Exmh_Status "$select(prompt) $f" return } } unset select(allfolders) catch {unset select(match)} Exmh_Status "$select(prompt) $select(sel)" } } proc SelectReturn { w {a {}} } { global select if [info exists select(folder)] { if {$a != {}} { SelectTypein $w $a return } if [info exists select(match)] { set select(sel) $select(match) unset select(match) } if [string length $select(sel)] { Folder_[lindex $select(toggle) 0] $select(sel) } unset select(folder) catch {unset select(allfolders)} } else { if [regexp {^[0-9]+$} $select(sel)] { Msg_Change $select(sel) show } } $select(entry) configure -state disabled Exmh_Focus } proc SelectCancel { w } { global select if [info exists select(folder)] { set select(toggle) { Change Target } unset select(folder) } $select(entry) configure -state disabled Exmh_Status "" Exmh_Focus } proc SelectClear { w } { global select set select(sel) {} Exmh_Status "$select(prompt) $select(sel)" } exmh-2.9.0/inc.expect0000755000170700017070000000334013370473410014005 0ustar valdisvaldis#!/bin/sh # \ exec /usr/bin/expect -f "$0" -- ${1+"$@"} # # Script to run inc and provide a password. # # When there is mail to incorporate, echo back only the message headers # for the FTOC. Otherwise, send back all text, for debug logging set timeout 60 gets stdin password # turn off echo so that password doesn't get echoed by tty driver set stty_init -echo eval spawn -noecho $argv log_user 0 # When .netrc exists, inc doesn't prompt for a password. After getting # a password one way or another, inc prints one of # Incorporating new mail into inbox...\r\n\r\n # inc: no mail to incorporate # # For the case of mail available, we want to drain the informational # line "Incorporating new mail" here, so it doesn't get sent back # as output and get stuck in the FTOC window, and proceed to the while # loop, below. # # If there's no mail, the informational message sent back, with exit 1, # so the message gets put into the debug log. # expect { -re "Password (.*):" { exp_send -- $password\n lappend incout $expect_out(buffer) $password\n expect { -re ".* new mail .*\n" {} eof { send_user $expect_out(buffer) exit 1 } timeout { send_user "timeout"; exit 1 } } } -re ".* new mail .*\n" {} eof { send_user $expect_out(buffer) exit 1 } timeout { send_user "timeout"; exit 1 } } # drain any empty line # echo back msg header for FTOC # if exit status of inc is non-zero (e.g., 1 for no mail), # echo back all accumulated text while {1} { expect { -re "^\[ \r\n]+$" {} -re ".*\n" { send_user $expect_out(buffer) } eof { if { [lindex [wait] 3] == 0 } { exit 0 } else { send_user $incout exit 1 } } } } exmh-2.9.0/version.csh0000755000170700017070000000101613201227060014173 0ustar valdisvaldis#!/bin/csh # To change the version, first edit the Makefile and # change the version there, and frob the patterns in # version.sed. Then type "make version" # You still want to add release notes to # exmh.README and probably the other html files. foreach f ( Makefile exmh.README lib/html/index.html lib/html/software.html ) echo $f sed -f version.sed < $f > $f.new mv $f $f.old mv $f.new $f diff $f.old $f end echo "Edit lib/html/exmh.README.html by hand" echo "Use PatchVersion to fix exmh.install" exmh-2.9.0/install.tcl0000644000170700017070000006317013201227060014167 0ustar valdisvaldis# # # install.tcl - Installation support # option add *Entry.background white startup option add *Entry.foreground black startup option add *Button.padX 1 startup option add *Button.padX 1 startup option add *Button.highlightThickness 0 startup option add *Entry.relief flat startup option add *Entry.highlightThickness 0 startup option add *font fixed startup option add *Text.c_link blue startup proc install_init { appName dotFile } { global install tk_version tk_patchLevel tcl_version tcl_patchLevel # Work around namespaces issue in Tk8.4a2 and later ::tk::unsupported::ExposePrivateCommand tkEntryBackspace set install(appName) $appName install_progVar wish [installGuessPath /usr/local/bin/wish wish] {wish absolute pathname} set install(dotFile) $dotFile if [file readable $dotFile] { if [catch {uplevel #0 source $dotFile} msg] { puts stderr "source $dotFile: $msg" } } else { if {[catch {glob ../$appName*/$dotFile} files] == 0} { installAlternates $files 1 } } } proc installAlternates { files isdefault } { wm withdraw . toplevel .config set fm [frame .config.rim -bd 10] message $fm.msg -aspect 1500 -text \ "Please select an alternate configuration." pack $fm -fill both -expand 1 pack $fm.msg set id 0 foreach f $files { button $fm.but$id -text $f -command [list installConfig $f $isdefault] pack $fm.but$id -fill both -expand 1 incr id } button $fm.but$id -text "Ignore configurations" -command installConfig pack $fm.but$id -fill both -expand 1 tkwait window .config wm deiconify . } proc installConfigs {} { global install if {[catch {glob ../$install(appName)*/$install(dotFile)*} files] == 0} { installAlternates $files 0 } } proc installConfig { {file {}} {isdefault 1} } { global install installFeedback "installConfig $file" if {$file != {}} { if [catch {uplevel #0 source $file} msg] { installFeedback $msg return } if {! $isdefault} { set install(dotFile) $file installUpdateAll } } destroy .config } proc install_var { var value {comment {}} } { global install lappend install(sequence) $var set install(field,$var) [list $var $value $comment] } proc install_version { var version {comment {}} } { global install if {$comment == {}} { if [info exists install(appName)] { set comment "$appName version stamp" } else { set comment {Version stamp} } } set install(versionVar) $var install_var $var $version $comment } proc install_name { name value comment } { global install set install(namevar) $name install_var $name $value $comment } proc install_dir { name value comment } { global install lappend install(dirlist) $name install_var install(dir,$name) $value $comment } proc install_glob { name args } { global install set install(glob,$name) $args } proc install_dirVar { var pathname comment } { install_var $var $pathname $comment global install lappend install(dircheck) $var set install(dircheck,$var) $comment } proc install_fileVar { var pathname comment } { install_var $var $pathname $comment global install lappend install(filecheck) $var set install(filecheck,$var) $comment } proc install_progVar { var pathname comment } { install_var $var $pathname $comment global install lappend install(progcheck) $var set install(progcheck,$var) $comment } proc install_sed { suffix args } { global install set install(sedSuffix) $suffix set install(sedProgs) $args } proc install_libDir {var pathname comment} { global install install_dirVar $var $pathname $comment set install(libDirVar) $var } proc install_testLib { pathname } { global install set install(testLib) $pathname } proc install_expect { var pathname comment } { install_var $var $pathname $comment global install set install(expectVar) $var lappend install(progcheck) $var set install(progcheck,$var) $comment } proc install_ps { var cmd comment } { install_var $var $cmd $comment global install set install(psVar) $var } proc installFieldVar { item } { lindex $item 0 } proc installFieldComment { item } { lindex $item 2 } proc installFieldDefault { item {override 0} } { set default [lindex $item 1] if {$override} { return $default } set varName [installFieldVar $item] if [catch {installGetValue $varName} value] { return $default } else { return $value } } proc installGuessDir { defpath file } { global env set tmp $defpath puts "installGuessDir: def=$defpath, file=$file..." foreach dir [split $env(PATH) :] { if {[file exists $dir/$file]} { set tmp $dir break } } puts "returning $tmp\n" return $tmp } proc installGuessPath { defpath file } { global env set tmp $defpath #puts "installGuessPath: def=$defpath, file=$file..." foreach dir [concat /etc /usr/lib/nmh [split $env(PATH) :]] { if {[file exists $dir/$file]} { set tmp $dir/$file break } } #puts "returning $tmp\n" return $tmp } proc install_help { text } { global install set install(helpText) $text } proc installFeedback { text } { global install catch { $install(msg) configure -text $text update } } proc installError { text } { puts stderr $text installFeedback $text } proc installFieldInit {} { global install set install(lastentry) {} } proc installDoField { item {override 0} } { global install if ![info exists install(wuid)] { set install(wuid) 0 } incr install(wuid) set f [frame .fields.import$install(wuid) -relief raised] set var [installFieldVar $item] button $f.label -text [format "%-30s:" [installFieldComment $item]] \ -command "installShowValue $var" -font fixed entry $f.entry -font fixed -width 40 $f.entry insert 0 [installFieldDefault $item $override] bind $f.entry [list installSetValue $var] if {$install(lastentry) != {}} { bind $install(lastentry) [list focus $f.entry] } else { set install(firstentry) $f.entry } set install(lastentry) $f.entry set install(entry,$var) $f.entry lappend install(allEntries) $f.entry pack $f -side top -expand true -fill both pack $f.label -side left -padx 3 pack $f.entry -side right -expand true -fill both return $f } proc installUpdateField { item {override 0} } { global install set var [installFieldVar $item] set entry $install(entry,$var) $entry delete 0 end $entry insert 0 [installFieldDefault $item $override] } proc installFieldDone {} { global install if {[info exists install(firstentry)] && \ [info exists install(lastentry)]} { bind $install(lastentry) [list focus $install(firstentry)] } } proc installSetValue { varName } { global install if [info exists install(entry,$varName)] { set value [$install(entry,$varName) get] upvar #0 $varName var set var $value } } proc installGetValue { var } { if [string match *(* $var] { set arrayName [lindex [split $var (] 0] global $arrayName } else { global $var } return [set $var] } proc installShowValue { var } { global install if [info exists install(entry,$var)] { installSetValue $var set entry $install(entry,$var) $entry select from 0 $entry select to end focus $entry } } proc installVerify {} { global install installFeedback "Checking Pathnames..." set errors {} if [info exists install(dircheck)] { foreach var $install(dircheck) { installSetValue $var set path [installGetValue $var] if {[string length $path] == 0} { continue } if ![file isdirectory $path] { set willMakeDir 0 foreach dirType $install(dirlist) { if {![info exist install(dir,$dirType)]} { installSetValue install(dir,$dirType) } set newdir $install(dir,$dirType) if {$newdir == $path} { set willMakeDir 1 } } if {! $willMakeDir} { lappend errors [format "%-30s <%s> %s" \ $install(dircheck,$var) $path "not a directory"] } } if ![regexp ^/ $path] { lappend errors [format "%-30s Warning: <%s> %s" \ $install(dircheck,$var) $path "is not an absolute pathname"] } } } if [info exists install(filecheck)] { foreach var $install(filecheck) { installSetValue $var set path [installGetValue $var] if {[string length $path] == 0} { continue } if ![file exists $path] { lappend errors [format "%-30s <%s> %s" \ $install(filecheck,$var) $path "does not exist"] } if ![regexp ^/ $path] { lappend errors [format "%-30s Warning: <%s> %s" \ $install(filecheck,$var) $path "is not an absolute pathname"] } } } if [info exists install(progcheck)] { foreach var $install(progcheck) { installSetValue $var ;# Snarf current value from entry set path [installGetValue $var] if {[string length $path] == 0} { continue } if ![file executable $path] { lappend errors [format "%-30s <%s> %s" \ $install(progcheck,$var) $path "is not executable"] } if ![regexp ^/ $path] { lappend errors [format "%-30s Warning: <%s> %s" \ $install(progcheck,$var) $path "is not an absolute pathname"] } } } if [info exists install(psVar)] { installSetValue $install(psVar) ;# Snarf current value from entry set cmd [installGetValue $install(psVar)] if [catch {eval exec $cmd [pid]} err] { lappend errors [format "%-30s Warning: <%s> %s" \ "ps command" "$cmd [pid]" $err] } } if {$errors != {}} { installFeedback "Verify errors" } else { installFeedback "Verify OK" return } if {[winfo exists .verify]} { destroy .verify } toplevel .verify frame .verify.top button .verify.top.quit -text "Dismiss" -command {destroy .verify} label .verify.top.label -text " Verify Errors " pack .verify.top -side top -fill both -expand true pack .verify.top.quit -side left pack .verify.top.label -side left -fill both set numLines [llength $errors] if {$numLines < 30} { text .verify.t -width 80 -height $numLines -font fixed pack .verify.t -side bottom -expand true -fill both } else { text .verify.t -width 80 -height 30 -yscrollcommand {.verify.s set} -font fixed scrollbar .verify.s -orient vert -command {.verify.t yview} pack .verify.s -side right -fill y pack .verify.t -side left -expand true -fill both } foreach line $errors { .verify.t insert end $line\n } } proc installSed { } { global install program set id 0 while {[catch {open /tmp/sed.$id w} script]} { incr id if {$id > 100} { installFeedback "installSed: Cannot create sed script in /tmp" return } } installSetValue wish ;# Get current value from entry widget set w [installGetValue wish] foreach sep {, ` ~ ? &} { if {![string match *$sep* $w]} { break } } puts $script "s$sep#!wish$sep#!$w$sep" # Set up for helper expect scripts, if needed and if possible if [info exists install(expectVar)] { installSetValue $install(expectVar) set pathname [installGetValue $install(expectVar)] if {$pathname != {}} { foreach sep {, ` ~ ? &} { if {![string match *$sep* $pathname]} { break } } puts $script "s${sep}exec expect${sep}exec $pathname$sep" } } # Insert configuration information puts $script /^#CONFIGURATION/a\\ foreach v $install(sequence) { set item $install(field,$v) set var [installFieldVar $item] installSetValue $var puts $script [list set $var [installGetValue $var]] nonewline puts $script \\ } puts $script "" close $script set name [installGetValue $install(namevar)] foreach prog $install(sedProgs) { regsub $program $prog $name newfile if [catch { exec sed -f /tmp/sed.$id < ${prog}$install(sedSuffix) > $newfile exec chmod a+x $newfile } msg] { installFeedback "sed error on $prog: $msg" } } exec rm /tmp/sed.$id } proc installPatch {} { global install program installSave installVerify installSed set sample [lindex $install(sedProgs) 0] set name [installGetValue $install(namevar)] regsub $program $sample $name name catch {exec diff -c ${sample}$install(sedSuffix) $name} diff catch {destroy .test} set numLines [llength [split $diff \n]] if {$numLines == 0} { installFeedback "No diffs after patching" return } if {[winfo exists .test]} { destroy .test } toplevel .test frame .test.top button .test.top.quit -text "Dismiss" -command {destroy .test} label .test.top.label -text " Context diff of $sample" pack .test.top -side top -fill both -expand true pack .test.top.quit -side left pack .test.top.label -side left -fill both installFeedback "$numLines lines of diff output" if {$numLines < 30} { text .test.t -width 80 -height $numLines -font fixed pack .test.t -side bottom -expand true -fill both } else { text .test.t -width 80 -height 30 -yscrollcommand {.test.s set} -font fixed scrollbar .test.s -orient vert -command {.test.t yview} pack .test.s -side right -fill y pack .test.t -side left -expand true -fill both } .test.t insert end $diff } proc install_test { args } { global install set install(test) $args } proc installTest {} { global install # Run patch again with testing library, if it is defined if {[info exists install(testLib)] && [info exists install(libDirVar)]} { set var $install(libDirVar) if [info exists install(entry,$var)] { set realValue [$install(entry,$var) get] $install(entry,$var) delete 0 end $install(entry,$var) insert 0 $install(testLib) installSed } } if [info exists install(test)] { set name [installGetValue $install(namevar)] regsub exmh $install(test) $name test installFeedback $test eval $test } else { installFeedback "No install_test command" } if [info exists realValue] { $install(entry,$var) delete 0 end $install(entry,$var) insert 0 $realValue } } proc installTclIndex {} { installFeedback "Refreshing ./lib/tclIndex" auto_mkindex ./lib *.tcl installFeedback "" } proc installButton {} { button .rim.buttons.yes -text "Really Install" -command {installInner} button .rim.buttons.no -text "Cancel" -command {installCancel} pack forget .rim.buttons.install pack .rim.buttons.no .rim.buttons.yes -side left } proc installSave { } { global install argv0 # Save it installSetValue install(dotFile) if [catch {open $install(dotFile) w} out] { installFeedback "Cannot write $install(dotFile)" return } if ![info exists argv0] { set argv0 $install(appName).install } puts $out "# Saved state from $argv0" puts $out "# [exec date]" foreach v $install(sequence) { set item $install(field,$v) set varName [installFieldVar $item] installSetValue $varName set value [installGetValue $varName] puts $out [list set $varName $value] } close $out installFeedback "Saved settings in $install(dotFile)" } proc installCancel {} { after 10 { destroy .rim.buttons.yes ; destroy .rim.buttons.no pack .rim.buttons.install -before .rim.buttons.quit -side left } } proc installCmd { logProc unixCmd } { if {$logProc != "nolog"} { $logProc $unixCmd } else { eval exec $unixCmd } } proc installInner { {logProc nolog} } { global install program installVerify installSed foreach dirType $install(dirlist) { # # Install directory - make sure it exists # set dir $install(dir,$dirType) MakeDir $logProc $dir if {($logProc == "nolog") && ![file isdirectory $dir]} { installError "LibDir $dir is not a directory" continue } if [info exists install(glob,$dirType)] { # # Tweak program name # if {$dirType == "bin"} { set newglob {} set name [installGetValue $install(namevar)] foreach pat $install(glob,bin) { regsub $program $pat $name pat lappend newglob $pat } } else { set newglob $install(glob,$dirType) } # # Install glob pattern - copy the files in # foreach f [eval glob $newglob] { if [catch { set t [file tail $f] if {$dirType == "man"} { # Hack to tweak file suffix set end [expr [string length $dir]-1] set suffix [string index $dir $end] set newf [file root $t].$suffix } else { set newf $t } if [file isdirectory $f] { installCmd $logProc [list rm -rf $dir/$newf] installCmd $logProc [list cp -r $f $dir/$newf] installCmd $logProc [list chmod a+rx $dir/$newf] installCmd $logProc [list chmod -R a+r $dir/$newf] } else { installCmd $logProc [list rm -f $dir/$newf] installCmd $logProc [list cp $f $dir/$newf] } if {$dirType == "bin"} { installCmd $logProc [list chmod a+rx $dir/$newf] } else { installCmd $logProc [list chmod a+r $dir/$newf] } } msg] { installFeedback "Dir install $f error: $msg" return } else { if {$logProc == "nolog"} { installFeedback "Installed $newf" } } } } } if {$logProc == "nolog"} { installCancel installFeedback "Install complete" } } proc MakeDir { logProc dir } { if [file isdirectory $dir] { return 1 } elseif [file exists $dir] { installError "LibDir $dir is not a directory" return 0 } else { if [MakeDir $logProc [file dirname $dir]] { installCmd $logProc [list mkdir $dir] installCmd $logProc [list chmod a+rx $dir] return 1 } else { return 0 } } } proc installFake {} { global exmh install if {[winfo exists .fake]} { destroy .fake } toplevel .fake wm title .fake "Install Actions" wm iconname .fake "Install Actions" frame .fake.top button .fake.top.quit -text "Dismiss" -command {destroy .fake} label .fake.top.label -text " Pending install actions" pack .fake.top -side top -fill x pack .fake.top.quit -side left pack .fake.top.label -side left -fill both text .fake.t -width 80 -height 20 -yscrollcommand {.fake.s set} -font fixed scrollbar .fake.s -orient vert -command {.fake.t yview} pack .fake.s -side right -fill y pack .fake.t -side left -expand true -fill both proc log { text } { .fake.t insert end $text\n } installInner log } proc install_dialog {} { global install wm title . "Exmh Install" wm iconname . "Exmh Install" wm minsize . 200 200 update idletasks installBindInit frame .x canvas .can -yscrollcommand ".x.scroll set" scrollbar .x.scroll -command ".can yview" pack .x.scroll -side right -fill y -padx 2 -pady 5 pack .can -in .x -side top -expand true -fill both -padx 5 -pady 5 pack .x -side top -expand true -fill both frame .fields -relief flat .can create window 0 0 -anchor nw -window .fields installFieldInit foreach v $install(sequence) { if {$v == $install(versionVar)} { set override 1 ;# over-ride saved value with new version num. } else { set override 0 } set f [installDoField $install(field,$v) $override] } installFieldDone tkwait visibility $f set bbox [.can bbox all] set dy [winfo height $f] .can config -scrollregion $bbox \ -width [winfo width .fields] \ -height [expr 10 * $dy] \ -yscrollincrement $dy frame .rim -bd 5 -relief flat pack .rim -side top -fill x set install(msg) [label .rim.feedback -text "" -anchor w -padx 10] pack $install(msg) -side top -expand true -fill both frame .rim.buttons -relief raised pack .rim.buttons -side top -expand true -fill both button .rim.buttons.quit -text "Quit" -command {exit} button .rim.buttons.keys -text "Keys" -command {installBindKeys} button .rim.buttons.conf -text "Conf" -command {installConfigs} button .rim.buttons.patch -text "Patch" -command {installPatch} button .rim.buttons.test -text "Test" -command {installTest} button .rim.buttons.verify -text "Verify" -command {installFake} button .rim.buttons.install -text "Install" -command {installButton} button .rim.buttons.tclindex -text "TclIndex" -command {installTclIndex} frame .rim.buttons.space -width 10 -height 10 button .rim.buttons.readme -text "I have read the instructions" \ -command install_pack_buttons pack .rim.buttons.readme -side left pack .rim.buttons.readme -side left pack .rim.buttons.quit -side right } proc install_pack_buttons {} { pack forget .rim.buttons.readme pack .rim.buttons.patch \ .rim.buttons.tclindex \ .rim.buttons.test \ .rim.buttons.verify \ .rim.buttons.space \ .rim.buttons.install -side left pack \ .rim.buttons.quit \ .rim.buttons.keys \ .rim.buttons.conf -side right } proc installUpdateAll {} { global install foreach v $install(sequence) { if {$v == $install(versionVar)} { set override 1 ;# over-ride saved value with new version num. } else { set override 0 } installUpdateField $install(field,$v) $override } } proc installBindInit {} { global install set install(key,selpaste) set install(key,seldelete) set install(key,backspace) set install(key,backspace2) set install(key,backspace3) set install(key,deleol) set install(key,delword) d ;# forwardly set install(key,delchar) set install(key,linestart) set install(key,lineend) set install(key,backword) b set install(key,forwword) f set install(key,backchar) set install(key,forwchar) installBindEntry } proc installBindKeys {} { global install toplevel .keys wm title .keys "Install Edit Preferences" wm iconname .keys "Install Edit Preferences" frame .keys.b pack .keys.b -side top -fill x button .keys.b.quit -text Dismiss -command {destroy .keys} button .keys.b.apply -text Apply -command installBindSet message .keys.msg -aspect 1500 -text \ "Key bindings for the installation tool. Changes *do not* carry over to $install(appName)" set f [frame .keys.p -bd 10] pack .keys.b .keys.msg .keys.p -side top -fill x pack .keys.b.quit .keys.b.apply -side right set width 0 foreach item [array names install] { if [string match key* $item] { set name [lindex [split $item ,] 1] set w [string length $name] if {$w > $width} { set width $w } } } foreach item [lsort [array names install]] { if [string match key* $item] { set name [lindex [split $item ,] 1] set keystroke $install($item) installKeyItem $f $width $name $keystroke } } } proc installKeyItem { frame width name keystroke } { global install frame $frame.$name label $frame.$name.label -text $name -width $width entry $frame.$name.entry set install(keyval,$name) $frame.$name.entry $frame.$name.entry insert 0 $keystroke lappend install(allEntries) $frame.$name.entry pack $frame.$name pack $frame.$name.label -side left pack $frame.$name.entry -side right -fill x -expand 1 } proc installBindSet {} { global install # Clear old bindings foreach item [array names install] { if [string match key,* $item] { set name [lindex [split $item ,] 1] bind Entry $install(key,$name) { } } } foreach item [array names install] { if [string match keyval,* $item] { set name [lindex [split $item ,] 1] set install(key,$name) [$install(keyval,$name) get] } } installBindEntry Entry } proc installBindEntry { {list {}} } { if {$list == {}} { installBindEntryInner Entry } else { foreach entry $list { installBindEntryInner $entry } } } proc installBindEntryInner { what } { global install # Modification bindings bind $what { } ;# no-op bind $what $install(key,selpaste) { catch { %W insert insert [selection get] } } bind $what $install(key,seldelete) { catch {%W delete sel.first sel.last} } set bsProc tkEntryBackspace foreach bs {backspace backspace2 backspace3} { bind $what $install(key,$bs) "$bsProc %W" } bind $what $install(key,deleol) { %W delete insert end } bind $what $install(key,delword) { info library } bind $what $install(key,delchar) { %W delete insert } bind $what $install(key,linestart) { %W icursor 0 } bind $what $install(key,lineend) { %W icursor end } bind $what $install(key,backword) { set string [%W get] set curs [expr [%W index insert]-1] if {$curs < 0} return for {set x $curs} {$x > 0} {incr x -1} { if {([string first [string index $string $x] " \t"] < 0) && ([string first [string index $string [expr $x-1]] " \t"] >= 0)} { break } } %W icursor $x } bind $what $install(key,forwword) { set string [%W get] set curs [expr [%W index insert]+1] set len [string length $string] if {$curs < 0} return for {set x $curs} {$x < $len} {incr x} { if {([string first [string index $string $x] " \t"] < 0) && ([string first [string index $string [expr $x+1]] " \t"] >= 0)} { break } } %W icursor $x } bind $what $install(key,backchar) { set x [%W index insert] if {$x > 0} { incr x -1 %W icursor $x } } bind $what $install(key,forwchar) { set x [%W index insert] incr x %W icursor $x } } proc install_html {html} { global install program auto_path exwin widgetText lappend auto_path ./lib option add *Text*background white option add *Text*foreground black option add *Text*highlightBackground white option add *Text*highlightColor black proc Exmh_Status {string} {installFeedback $string} Env_Init set widgetText(smoothScroll) 0 set exwin(mtext) [Html_Display $html file:[file join [pwd] [info script]]] } exmh-2.9.0/COPYRIGHT0000644000170700017070000000271013201227060013301 0ustar valdisvaldisCopyright 2000-2003 Brent Welch. All rights reserved. Copyright 1999 Scriptics Corporation. All rights reserved. Copyright 1995-8 Sun Microsystems Laboratories. All rights reserved. Copyright 1993-5 Xerox Corporation. All rights reserved. License is granted to copy, to use, and to make and to use derivative works for any purpose, provided that the copyright notice and this license notice is included in all copies and any derivatives works and in all related documentation. Xerox, Sun, and Ajuba Solutions grant no other licenses expressed or implied and the licensee acknowleges that Xerox, Sun and Ajuba Solutions have no liability for licensee's use or for any derivative works made by licensee. The Xerox and Sun names shall not be used in any advertising or the like without their written permission. This software is provided AS IS. XEROX CORPORATION, SUN MICROSYSTEMS, SCRIPTICS, AND BRENT WELCH DISCLAIM AND LICENSEE AGREES THAT ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS EXPRESSLY DISCLAIMED, INCLUDING CONSEQUENTIAL OR ANY OTHER INDIRECT DAMAGES, WHETHER ARISING IN CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION, SUN MICROSYSTEMS OR AJUBA SOLUTIONS IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. exmh-2.9.0/exmh-async.MASTER0000755000170700017070000000151113201227060015000 0ustar valdisvaldis#!wish -f # # async editor frontend for exmh # Arg1: invoking interpreter's name (from [winfo name .]) # Arg2-end: editor command, including pathname # LastArg: pathname of draft message # package require Tk wm withdraw . # simple argv cracking set exmh [lindex $argv 0] set editorCmd [lrange $argv 1 end] set draftpath [lindex $argv [expr {[llength $argv] - 1}]] set draftm [file tail $draftpath] send $exmh [list Edit_Ident [winfo name .]] # Used to do a split/join on $editorCmd to allow quoted -geom arguments. # But that totally screws some arguments, like # exmh-async gvim -c {cal SetSyn("mail")} # other interesting cases are # exmh-async xterm -geom +0+0 -e vi {+/^[-]*$} if [catch {eval exec $editorCmd} err] { send $exmh [list Exmh_Status "exmh-async: editor failed: $err" purple] } send $exmh EditDialog $draftm exit 0 exmh-2.9.0/exmh.BUGS0000644000170700017070000002051613201227060013435 0ustar valdisvaldis Number: 1 Version: 2.1.0 Priority: Medium Scope: Narrow Complexity: Easy Status: Harry G. McGavran Jr. reports on exmh-users that double-clicking the iconified window still refuses to de-iconify. My recollection is that a 1 or 2 line fix was posted to exmh-workers a while back, but I can't find it in the archive. - slipcon These are known bugs in exmh, along with the release under which they were reported. ---------------------------------------------------------------------- Number: 3 Version: 2.0.3 Priority: Low Scope: Narrow Complexity: Medium Status: This is an old bug. The MIME display code misses one part of the RFC's requirements on multiparts in which the number of CRLFs at the end of a section have a meaning that I don't actually recall at the moment. I discovered it a while after I wrote the code. It probably isn't hard, but I haven't looked at that code in 5 years or more. ---------------------------------------------------------------------- Number: 5 Version: 2.0.3 Priority: Medium Scope: Narrow Complexity: ? Status: Not cleaning up MIME parts saved into temp files. Not cleaning up audit logs. ---------------------------------------------------------------------- Number: 6 Version: 2.0.3 + cvs as of around 4/7 Priority: Low Scope: Narrow Complexity: ? Status: Bug 10 was fixed. Someone thought this might be a duplicate of that. Was it? I-Spell gets turned off by magic. Make the magic go away. ---------------------------------------------------------------------- Number: 7 Version: 2.0.3 Priority: Low Scope: Narrow Complexity: ? Status: The "use message as draft" does not highlight the body (not obeying the "colorize multipart" preference?). ---------------------------------------------------------------------- Number: 9 Version: 2.0.3 Priority: Low Scope: Narrow Complexity: ? Status: A URL of the form "http://host.dom" without a trailing slash doesn't work. Subject: Re: exmh built in browser bug? Date: Wed, 14 Apr 1999 11:17:20 -0700 (13:17 CDT) From: Brent Welch We should fix it to use the http:: package, if available. I also noticed there is no timeout on Http_get. ---------------------------------------------------------------------- Number: 11 Version: 2.0.2 Priority: ? Scope: ? Complexity: ? Status: Message received at submit@bugs.debian.org: From: "Thomas Gebhardt" Package: exmh Version: 2.0.2-1 Hi, sometimes I get a message with MIME encoded iso-latin characters with a header like Mime-Version: 1.0 Content-Type: multipart/signed; boundary="-==--=-=-=======--==--=-=--=-===---===----=--==="; protocol="application/pgp-signature"; micalg=pgp-sha1 ---==--=-=-=======--==--=-=--=-===---===----=--=== Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable .... message text .... ---==--=-=-=======--==--=-=--=-===---===----=--=== Content-Type: application/pgp-signature -----BEGIN PGP MESSAGE----- Version: PGPfreeware 5.5.3i for non-commercial use iQA/AwUBNZOc0qMJGtg+zqPAEQKTsgCg7+JhDM/BnXCnoWZebJGyZmMBxzoAoLbP stDjIbtFhQEP+EiReo3uqVME =4ohD -----END PGP MESSAGE----- ---==--=-=-=======--==--=-=--=-===---===----=--===-- When I reply to such a message and use the "Quote" Button to quote parts of the message text, then the iso-latin characters do not show up correctly in the quoted text. They are displayed like "=F6" , i.e. as MIME codes. This seems to be a bug report for the upstream maintainer. Cheers, Thomas ---------------------------------------------------------------------- Number: 12 Version: 2.0.2 Priority: ? Scope: ? Complexity: ? Status: Message received at submit@bugs.debian.org: From: Martin Weinberg Setting FACEPATH as documented in /usr/doc/exmh/README.debian results in a display of arbitrary faces. I have not been able to figure out the logic error in faces.tcl. Picons behave properly if FACEPATH is not set. ---------------------------------------------------------------------- Number: 13 Version: 1.6.9 Priority: ? Scope: ? Complexity: ? Status: Message received at submit@bugs.debian.org: From: Dominik Kubla The exmh frontend can not handle inc contacting a POP server and asking for a password. ---------------------------------------------------------------------- Number: 14 Version: 1.6.9 Priority: ? Scope: ? Complexity: ? Status: [This may be impossible to fix, since PGP doesn't really output any useful exit status] Message received at submit@bugs.debian.org: From: Lars Wirzenius If I change PGP to use some other language than English, exmh loses it's ability to verify PGP messages. This is because it checks the output of PGP to see if it has a message that indicates a good signature. The pattern matches English only. This could be fixed to have exmh support all languages, or to force PGP to use English when run from exmh. I don't know if either is feasible without modifying either program heavily (and if either is going to be modified, it should be exmh, I think; PGP is a security tool, and should not be modified lightly). I have no fix, and the problem is not Debian-specific. It may be good to just forward this to the upstream authors. ---------------------------------------------------------------------- Number: 16 Version: 2.0.2 maybe earlier Priority: ? Scope: ? Complexity: ? Status: From: Anders Eriksson Date: Thu, 01 Apr 1999 14:27:43 +0200 Hi, This is a bug that has been bugging me for some time now. When I use mouse-base cut&paste the stuff pasted into the buffer is often something I cut&pasted several iterations ago. Is this a exmh or tk bug? I use exmh-2.0.2 (no patches) tcl/tk-8.0 fvwm2 Linux-2.0.36 From: Brent Welch Date: Fri, 02 Apr 1999 13:59:44 -0800 This is an exmh bug... ---------------------------------------------------------------------- Number: 19 Version: 2.0.2 Priority: Low Scope: Narrow Complexity: Probably easy Status: In Ispell, when you change default language selections there is often an uncaught error from a pipe close. error flushing "file9": broken pipe while executing "flush $ispellVars(spell_buffer)" (procedure "Ispell_Init" line 52) invoked from within "Ispell_Init" invoked from within ".sedit1.f.t.m.sub invoke active" ("uplevel" body line 1) invoked from within "uplevel #0 [list $w invoke active]" (procedure "tkMenuInvoke" line 29) invoked from within "tkMenuInvoke .sedit1.f.t.m.sub 1" ---------------------------------------------------------------------- Number: 20 Version: 2.0.2 Priority: Med Scope: Narrow Complexity: ? Status: Date: Fri, 23 Apr 1999 11:36:04 -0400 (10:36 CDT) From: Chip Christian The url-scanning code only looks for one url per line, but sometimes I get messages with more. ---------------------------------------------------------------------- Number: 21 Version: 2.0.2 Priority: Low Scope: Narrow Complexity: Doc only Status: The Hook_SeditInit predefined hooks are not mentioned in the html doc. There might be others, review the code and document any missing ones ---------------------------------------------------------------------- Number: 22 Version: 2.0.2 Priority: medium Scope: Narrow Complexity: Status: Found this in Intro.html: BUG: if you have projected a New FTOC, a subsequent pick will only select messages still on the display. You need to rescan the folder to start over. Sigh. ---------------------------------------------------------------------- Number: 23 Version: 2.1.0 Priority: medium Scope: Narrow Complexity: Status: Pgp_Exec sometimes indicates a PGP operation has failed when it actually suceeded. As far as I can tell the problem is that in a [catch {exec $cmd}] the catch gets triggered if the cmd uses stderr. Some form of smarter error checking seems necessary. - kchrist ---------------------------------------------------------------------- Number: 24 Version: 2.1.0 Priority: medium Scope: Narrow Complexity: Status: Detected a pgpMatch failure. While trying to match user@hotmail.com a key search for @hotmail.com was done. The search returned wronguser@hotmail.com (single match) and the key was used although user != wronguser. I suspect having a single match for a key may be responsible here. - kchrist exmh-2.9.0/exmh.MASTER0000755000170700017070000000710513201227060013672 0ustar valdisvaldis#!wish -f # # TK interface to the MH Mail utility # Brent Welch # Original version by # # Copyright (c) 1993-8 Brent Welch # Copyright (c) 1993-5 Xerox Corporation. # Copyright (c) 1996-8 Sun Microsystems # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # and Sun Microsystems # make no warranty about the software, its performance or its conformity to # any specification. # The following lines are patched by exmh.install #CONFIGURATION #END CONFIGURATION package require Tk if {$tcl_version < 8.5} { error "Tcl 8.5 or higher required." exit 1 } # Do this so popups related to user initialization # appear all alone. wm withdraw . # fonts in tk8.5: short aliases like don't work properly anymore # (confusion with the font face stuff) # recreate the common fallback "fixed" as a copy of TkFixedFont eval font create fixed [font configure TkFixedFont] proc auto_path_update { path } { # Add library directories to the auto_path, # ensuring that later paths have precedence # and that function override works global auto_path tk_version if [file exists $path/tclIndex] { set auto_path "$path $auto_path" # Used to have an "auto_reset" here, but that has the bad # side effect of causing Tk's entry.tcl and text.tcl files # to reload and redefine top-level Entry and Text bindings # that we change in seditBind.tcl. # catch {auto_reset} ;# Needed for function override } } auto_path_update $exmh(library) if ![file exists $exmh(library)/tclIndex] { if [file exists ./lib/tclIndex] { puts stderr "Warning, using local script library, ./lib" set exmh(library) ./lib } } # Support per-user directory containing .tcl files. # This was originally the ~/.tk/exmh directory, # but then files migrated into ~/.exmh so # a lib subdirectory there is cleaner foreach exmh(userLibrary) [list [glob ~]/.exmh/lib [glob ~]/.tk/exmh] { if {[file exists [file join $exmh(userLibrary) tclIndex]]} { auto_path_update $exmh(userLibrary) ;# library for new modules break } } # Fall through with ~/.tk/exmh as the default because there # are other places in the code that assume exmh(userLibrary) is defined # Set up the environment if {[catch { Env_Init } err]} { puts stderr "Error running Env_Init: $err" puts stderr "This usually means exmh isn't installed right" puts stderr "Check the main exmh script for the CONFIGURATION section" puts stderr "and make sure exmh(library) is a valid absolute pathname" exit 1 } # For WindowMaker, http://www.inf.ufrgs.br/~kojima/wmaker/ wm group . . # For session managers wm command . "$argv0 $argv" catch {wm client . "[exec hostname]"} catch { . configure -cursor left_ptr } # modified by k.furukawa, jul.1994. for kanji # this piece of code enables japanese kanji display if you use # tk-jp extension and JIS code. if you use EUC for MH processing # codes, you may replace JIS with EUC and you may need more works. if {[info commands kanji] == "kanji"} { kanji internalCode JIS option add *Text.Font a14 } # Ensure the user is in a writable directory for @ links if {[string match /* $exmh(library)] && [string match /* $argv0]} { # Don't go anywhere when testing cd } # The rest of the application is defined by routines in the exmh library # The after 1 trick is to ensure we get the built-in error handler. after 1 {Exmh} exmh-2.9.0/PatchVersion0000755000170700017070000000055013201227060014341 0ustar valdisvaldis#!/bin/sh # \ exec tclsh "$0" ${1+"$@"} set version [lindex $argv 0] set out stdout set in stdin while {[gets $in line] >= 0} { if {[regexp "^set vers" $line]} { puts $out [list set vers $version] } elseif {[regexp "^set date" $line]} { puts $out [list set date [clock format [clock seconds] -format %m/%d/%Y]] } else { puts $out $line } } exmh-2.9.0/Makefile.old0000644000170700017070000000531413370471637014250 0ustar valdisvaldis# Create a tar distribution for exmh # To change the version, # change this variable and type "make version" VERSION=2.9.0 RELDATE:=$(shell grep '^set date' ./exmh.install | cut -f3 -d" ") SNAPRELDATE:=$(shell /bin/date +%m/%d/%Y) SNAPDATE=`/bin/date +%Y%m%d` # Don't add "version" to the srctar production because it may # re-write files we've tinkered with by hand (e.g., lib/html/exmh.README.html) srctar: realsrctar realsrctar: htmltar find . -name CVS > Tar.exclude echo ./lib/html/Tar.exclude >> Tar.exclude echo ./.exmhinstall >> Tar.exclude echo ./Tar.exclude >> Tar.exclude echo ./html-\*.tar.gz >> Tar.exclude echo ./exmh-\*.tar.gz >> Tar.exclude echo ./exmh-\*.src.rpm >> Tar.exclude echo ./exmh-\*.noarch.rpm >> Tar.exclude echo ./rpmroot >> Tar.exclude echo ./exmh-$(VERSION) >> Tar.exclude echo ./exmh-$(VERSION).tar.gz >> Tar.exclude echo ./html-$(VERSION).tar.gz >> Tar.exclude rm -rf ./exmh-$(VERSION) mkdir ./exmh-$(VERSION) tar cvfX - Tar.exclude . | (cd ./exmh-$(VERSION) ; tar xf -) (tar cf - exmh-$(VERSION) | gzip > ./exmh-$(VERSION).tar.gz) rm -rf ./exmh-$(VERSION) clean: rm -f ./Tar.exclude rm -f ./lib/html/Tar.exclude rm -f ./exmh-*.tar.gz rm -f ./html-*.tar.gz rm -f ./exmh-*.noarch.rpm rm -f ./exmh-*.src.rpm rm -f ./lib/html/exmh.CHANGES.txt rm -rf ./rpmroot/ rm -rf ./exmh-$(VERSION) rpm: realsrctar mkdir -p rpmroot/{SOURCES,SPECS,BUILDROOT,RPMS/noarch,SRPMS,BUILD} cp exmh-$(VERSION).tar.gz rpmroot/SOURCES/ sed -e 's/VERSION/$(VERSION)/g' -e 's#RELDATE#$(RELDATE)#g' < misc/RPM/exmh-conf.patch > rpmroot/SOURCES/exmh-$(VERSION)-conf.patch cp misc/RPM/exmh.wmconfig rpmroot/SOURCES/ cp misc/RPM/exmh.desktop rpmroot/SOURCES/ sed 's/EXMHVERSION/$(VERSION)/g' < misc/RPM/exmh.spec > rpmroot/SPECS/exmh.spec rpmbuild -ba --define "_topdir `pwd`/rpmroot" --buildroot `pwd`/rpmroot/BUILDROOT rpmroot/SPECS/exmh.spec cp rpmroot/RPMS/noarch/exmh-$(VERSION)-?.noarch.rpm . cp rpmroot/RPMS/noarch/exmh-misc-$(VERSION)-?.noarch.rpm . cp rpmroot/SRPMS/exmh-$(VERSION)-?.src.rpm . snaprpm: make rpm VERSION=$(VERSION)_$(SNAPDATE) RELDATE=$(SNAPRELDATE) snaptar: make realsrctar VERSION=$(VERSION)_$(SNAPDATE) version: ./version.bash ./PatchVersion $(VERSION) < exmh.install > exmh.install.new mv exmh.install.new exmh.install ftpdist: scp exmh-$(VERSION).tar.gz www.tcl.tk:~ftp/pub/tcl/exmh scp html-$(VERSION).tar.gz www.tcl.tk:~ftp/pub/tcl/exmh scp exmh.README www.tcl.tk:~ftp/pub/tcl/exmh scp lib/html/exmh.README.html www.tcl.tk:~ftp/pub/tcl/exmh htmltar: echo CVS > lib/html/Tar.exclude echo Tar.exclude >> lib/html/Tar.exclude cp exmh.CHANGES lib/html/exmh.CHANGES.txt (cd lib/html ; tar cfX - ./Tar.exclude . | gzip > ../../html-$(VERSION).tar.gz) install: srctar ftpdist exmh-2.9.0/exmh.README.old0000644000170700017070000000312313201227060014402 0ustar valdisvaldisSun Jan 2 20:56:42 PST 2005 welch@acm.org exmh is a TCL/TK based interface to the MH mail system. MH can be found at http://www.mhost.com/nmh/ Version 2.7.2 requires Tcl/Tk 8.3 or higher - works with the latest (8.4.5) All the docs have moved into html and are viewable from within the installer as well as from within a running exmh. The exmh home page is http://www.beedub.com/exmh/ Exmh builds on many related software packages: http://www.beedub.com/exmh/software.html Exmh sources live at SourceForge under http://sourceforge.net/projects/exmh/ To install, run wish exmh.install You can send me email with the word "exmh" in the subject, but you may get better response from the exmh-users mailing list. Subscribe via "exmh-users-request@redhat.com" Send a message whose subject line reads 'subscribe' and whose From or Reply-To line contains the email address to add. Thanks to the dozen or so folks that have write access to the CVS code base who continue to add features and fix bugs. You see these folks listed in the exmh.CHANGES file: cwg Chris Garrigues iko Anders Hammarquist haldevore Hal DeVore jbeck John Beck slipcon Scott Lipcon gruber Markus Gruber jrennie Jason Rennie valdis Valdis.Kletnieks@vt.edu bmah bmah@CA.Sandia.GOV (Bruce A. Mah) kchrist Kevin.Christian@lsil.com jmorzins Jacob Morzinski aer Anders Eriksson stanton Scott Stanton exmh-2.9.0/exmh.README0000644000170700017070000000312313370471644013645 0ustar valdisvaldisSun Jan 2 20:56:42 PST 2005 welch@acm.org exmh is a TCL/TK based interface to the MH mail system. MH can be found at http://www.mhost.com/nmh/ Version 2.7.2 requires Tcl/Tk 8.3 or higher - works with the latest (8.4.5) All the docs have moved into html and are viewable from within the installer as well as from within a running exmh. The exmh home page is http://www.beedub.com/exmh/ Exmh builds on many related software packages: http://www.beedub.com/exmh/software.html Exmh sources live at SourceForge under http://sourceforge.net/projects/exmh/ To install, run wish exmh.install You can send me email with the word "exmh" in the subject, but you may get better response from the exmh-users mailing list. Subscribe via "exmh-users-request@redhat.com" Send a message whose subject line reads 'subscribe' and whose From or Reply-To line contains the email address to add. Thanks to the dozen or so folks that have write access to the CVS code base who continue to add features and fix bugs. You see these folks listed in the exmh.CHANGES file: cwg Chris Garrigues iko Anders Hammarquist haldevore Hal DeVore jbeck John Beck slipcon Scott Lipcon gruber Markus Gruber jrennie Jason Rennie valdis Valdis.Kletnieks@vt.edu bmah bmah@CA.Sandia.GOV (Bruce A. Mah) kchrist Kevin.Christian@lsil.com jmorzins Jacob Morzinski aer Anders Eriksson stanton Scott Stanton exmh-2.9.0/misc/0000755000170700017070000000000013201227060012741 5ustar valdisvaldisexmh-2.9.0/misc/sequence.patch0000644000170700017070000001414213201227060015574 0ustar valdisvaldisThis is a patch that reflects a non-trivial change I made to how exmh tracks changes in the unseen sequence. The original behavior uses a Tcl variable trace on an array variable that gets updated for a lot of reasons. This can be expensive and so this patch reflects a change away from this specific variable trace. However, I don't think this change is 100% perfect, and you may notice less than perfect updates to the UI because of this change. So, instead of committing this I'm just saving the patch in case someone wants to tinker with it. Brent Welch, April 2012 cvs diff: Diffing lib Index: lib/fcache.tcl =================================================================== RCS file: /cvsroot/exmh/exmh/lib/fcache.tcl,v retrieving revision 1.13 diff -u -r1.13 fcache.tcl --- lib/fcache.tcl 5 Apr 2003 01:24:35 -0000 1.13 +++ lib/fcache.tcl 21 Apr 2012 20:08:12 -0000 @@ -68,7 +68,8 @@ trace variable fcache(nicknames) w Fcache_Redisplay trace variable fcache(unseenCount) w Fcache_Redisplay - trace variable flist wu Fcache_RedisplayUnseen + # This is an expensive trace. See SeqSetCount + # trace variable flist wu Fcache_RedisplayUnseen # Init the cache and handle various error cases. @@ -96,11 +97,10 @@ proc Fcache_Redisplay { args } { Fcache_Display 1 } -proc Fcache_RedisplayUnseen { array elem op } { +proc Fcache_RedisplayUnseen { seq } { global fcache mhProfile if {$fcache(unseenCount)} { - set force [scan $elem "seqcount,%s,$mhProfile(unseen-sequence)" folder] - Fcache_Display $force + Fcache_Display [expr {"$seq" == "$mhProfile(unseen-sequence)"}] } } Index: lib/mh.tcl =================================================================== RCS file: /cvsroot/exmh/exmh/lib/mh.tcl,v retrieving revision 1.60 diff -u -r1.60 mh.tcl --- lib/mh.tcl 18 Jun 2008 09:53:53 -0000 1.60 +++ lib/mh.tcl 21 Apr 2012 20:08:12 -0000 @@ -578,6 +578,12 @@ # Directly modify the context files to add/remove/clear messages # from a sequence proc Mh_SequenceUpdate { folder how seq {msgids {}} {which public}} { + Exmh_Debug Mh_SequenceUpdate $folder $how $seq $msgids $which + Mh_SequenceUpdateTimed $folder $how $seq $msgids $which + Exmh_Debug Mh_Sequence Update complete +} + +proc Mh_SequenceUpdateTimed { folder how seq {msgids {}} {which public}} { global mhProfile mhPriv if {0} { Exmh_Debug Mh_SequenceUpdate $folder $how $seq $msgids $which Index: lib/sequences.tcl =================================================================== RCS file: /cvsroot/exmh/exmh/lib/sequences.tcl,v retrieving revision 1.24 diff -u -r1.24 sequences.tcl --- lib/sequences.tcl 7 Jan 2005 06:09:09 -0000 1.24 +++ lib/sequences.tcl 21 Apr 2012 20:08:12 -0000 @@ -174,7 +174,7 @@ SeqWin_Init - # This trace is crude, and now we do all the updating in + # This trace is expensive, and now we do all the updating in # procedures in this file, so the calls are made explicitly. # trace variable flist wu Seq_Trace # Seq_Trace is now SeqCount @@ -186,11 +186,15 @@ # flist($seq) is the list of folders that have messages # in that sequence. Here we ensure that invariant. set num $flist(seqcount,$folder,$seq) - ldelete flist($seq) $folder + set ix [lsearch $flist($seq) $folder] if {$num > 0} { - lappend flist($seq) $folder + if {$ix < 0} { + lappend flist($seq) $folder + } } elseif {![info exist flist($seq)]} { set flist($seq) {} + } elseif {$ix >= 0} { + ldelete flist($seq) $folder } # Now tally up any changes if [info exists flist(oldseqcount,$folder,$seq)] { @@ -217,6 +221,13 @@ BgRPC SeqWinShowSeqPane $seq } } +# This procedure replaces an expensive trace on the flist var from fcache.tcl + +proc SeqSetCount {folder seq count} { + global flist mhProfile + set flist(seqcount,$folder,$seq) $count + Fcache_RedisplayUnseen $seq +} # Reset the cached state about sequences because the user # has just packed, sorted, or threaded the folder. @@ -228,7 +239,7 @@ global flist Mh_SequenceUpdate $folder clear $seq set flist(seq,$folder,$seq) {} - set flist(seqcount,$folder,$seq) 0 + SeqSetCount $folder $seq 0 ldelete flist($seq) $folder } @@ -276,7 +287,7 @@ if {$num <= 0} { return } - set flist(seqcount,$folder,$seq) [expr $new + $num] + SeqSetCount $folder $seq [expr {$new + $num}] set flist(seq,$folder,$seq) [concat $flist(seq,$folder,$seq) $msgids] if {![info exist flist($seq)] || ([lsearch $flist($seq) $folder] < 0)} { lappend flist($seq) $folder @@ -301,23 +312,26 @@ # Mh_SequenceUpdate $folder replace $seq $msgids set newnum [llength $msgids] if {$newnum <= 0} { - set flist(seqcount,$folder,$seq) 0 + SeqSetCount $folder $seq 0 set flist(seq,$folder,$seq) {} SeqCount $folder $seq return } - set flist(seqcount,$folder,$seq) $newnum +Exmh_Debug flist(seqcount) [time { + SeqSetCount $folder $seq $newnum set flist(seq,$folder,$seq) $msgids - if {![info exist flist($seq)] || ([lsearch $flist($seq) $folder] < 0)} { - lappend flist($seq) $folder + if {![info exist flist($seq)]} { + # SeqCount will append $folder to flist($seq) if necessary + set flist($seq) {} } - SeqCount $folder $seq +}] + Exmh_Debug SeqCount $folder $seq [time {SeqCount $folder $seq}] if {$seq == $mhProfile(unseen-sequence)} { if {[string compare $folder $exmh(folder)] != 0 && [lsearch $flist(unvisited) $folder] < 0} { lappend flist(unvisitedNext) $folder } - Fdisp_HighlightUnseen $folder + Exmh_Debug Fdisp_HighlightUnseen [time {Fdisp_HighlightUnseen $folder}] } } # Deletes messages from a sequence @@ -349,7 +363,9 @@ } proc Seq_Msgs { folder seq } { global flist - Seq_Set $folder $seq [Mh_Sequence $folder $seq] +Exmh_Debug Mh_Sequence $folder $seq [time {set s [Mh_Sequence $folder $seq]}] +# Seq_Set $folder $seq [Mh_Sequence $folder $seq] +Exmh_Debug Seq_Set $folder $seq [time {Seq_Set $folder $seq $s}] return $flist(seq,$folder,$seq) } proc Seq_Count { folder seq } { cvs diff: Diffing lib/bitmaps cvs diff: Diffing lib/html exmh-2.9.0/misc/Par150.tar.gz0000644000170700017070000013332513201227060015047 0ustar valdisvaldis‹w¥1Par150.tarì €rQ.®ƒ|B#JÒ8óY"3"Œhú åÃ,ªŸL|Ÿå¾/ÇÝɄ֊LÓiv ýV13ˆaý0AýJY CÃ2çA8qôòÙ3ç\‘¤±¶v¾h·D¯…ðÆXíÇã£ó§§¦ê8•r-ÉÓ–ó@F~0šðXſøtI{oD{¤Y> ßtI ÀÀ~Úm¢Ác`2¾F•È)Œ…†Âž¨îRu‘2„›º7™‚Þ[ ŽŠéäU‘-cS3r„ÖÖd›—…¨˜&©¼ â"ëâŹ"$xˆýz(Uº&c¦Ú °ve€¥~hXYçY‰Iê8Cé“yǰ/ŽÒ@ ü5_®ÕÞl= ˆ/ZòM·ƒß!Þ2ÿPÌkœ¨RºúZìŠþ`S<*e 낵ÖÏ¿›-«ò&5†áz ”н5mß›V‹QyÓPñãçLSCÃo4ZûØ×ˆû©F‹ä–$×KfkL”N\äñx*§ÔXˆK°Ú"YIãKÞ)Ô•r¡ÒìVÆMÏŒÙå{eÁô­2$xËt6¥¤àPÞSàR(@)ËJ1dT¤¨[6-)n˜¦žhÒ)ÎBq›‡e«½U¬ÈÆI\8ŠEQ(mñt€WšÎ[—•.UĦr¾¶À󸀪ÉVRâk ¦’T#šÑΧ KQIdMt„~= B©b.Cƒ’Þ¦¦0"¶POÑG¡lp-]Ú2ò`ÂŒÄ ¥›Þ>ZŒµ¦‘žÃ9l[z5¾kIª‰[IƒvÉ,Ì:ä¶ä–Î/²6ÀÜÜf(æ¦W©6UF*ô‡N)VÖ@w+­٠x4óó><Ñ•l‹5Caj»L€[‚{'Ëcc0ounµ<Æú¸±>øy§~më ¸ ðŸ3¦¼Ñ"”­ÍŠ)ú¦"qõ–¶õ1å5;S¢ßhÕ(H¥€HpLÑåGÇ´4\-@¥*å;‚E×[‹äè›oªÈ/1yðP‘ܘ;’!Òr¼ZfØPÃÈ[+¦¼ÎY¢ûsò^ÝÛho¹]®¨*ºÜ¨¹„X©®é°®Í£;kkî–Í¡]V‡VÕøã°KeŠ'ðôN“u¬ž«Vdnµµâ>/2¸ó2™VDÑ ÛÇÊ  ”áŽX$À˧ãÔâ}*¯Á_X8ÇÔ<úÙäs”be–#spìXÎUÙعàªNskžeJ,¯4´”¿ÚE»*¡-ƒhý-ÈÔ¦‘&¢•ˆ›‰¥Ù_#y³ùôWÄÿ&Ÿ!þ×ÛÜØÞTñ¿ÁFo[Çÿ¶¾Æÿ¾ˆøßäËŠÿŹ| Uâ ¯ED»LøÒ a9ë 2€à°{áÃZ+ÎE•4¨ºáµ;Ã(›çIéw0žvøÐœ–îùDÎhqœ¸Y…Wnˆ^nzYLA²n=€giµàÛœù8[AþùÀå6Y%IÙÄÔU5”ñ€e¾Hb˜¬¡ôÿLÜ€ õb ˜p“8ô3å—‚ÃJó¶†Þ5Í”>-(€–cª×âTõK‘™8c7‹TvMèsÙâL«ú˜ý¢Œ50qÆ)ð'Ëb/psà…E5Z¥Ë©;ÓxÈGwLD@éòÀ?èZÑØ¥«,Sí9Rx_Z¦sŒÔ0ÝÆiÂÝ?%o.04{ëPÑ2™WQ$C<·'1³éw6B³{_?uÿ×H@ëO“pËþÿöfGûÿƒím®·µùÕÿÿ¼þ¿‘‰/Êÿ"=]ú|¾RG\ÃTçF«9ZpÖ;¯æÏ8›<ØÚå]ð=ÒŒ§»TÂÐl(ØÏÌáLíqš¡}Ie‚V l ™&=vœbâ‚­Ndop F­ œXš\Ó¸ˆØEÐ>ŸÝ«Åþ) G7-ÀC€º8…O“0à98ÇÔ‚)‘&[y“(J,J1Ь|ƒî’oag Ôò ìÄјè°,;a~×ZVyØç¢”„ÛRü æÙÇO]ÐK¼y‰»ðuò²qè‚_94¹ Š!âÀT…@ú¡¢ë¾‘Iœ²øÉ®žÉ‹Y dPC›¦ž)O2_±™éè (\pÁ  Ñê`nú  Spë*Jõ^ÀØuD6tÔBÔE: ހ쬨…§¦¨ÀŸlØ0ÌH¨ñ¢rÊ›ž-æH†1&_Ä´8Sž´b$ÁûJÁº]+AoºÇ`ä®QïÕÀ„\™\?>]EWóR~JÛcBŒ¼„>‹ iIæjYyl)LVyà©Å ¡ÅþÙë—û{g¸wÞQ‰J­pEZ$¸ñ\°f¡Ì™5 u`=S° °`dïëÇßÏq›¾–/½VÂ.ƒ¼žÒÐ D.vÅ·Ã*,$>3¢g¯ìÅÈ+:EƒˆCž^T³êd¨ÏȽP顸xh…1lŽ+2¨‚·¼‚ÖägÖõÜ ù›P09Fn#ÿÝ'’ý^Æw=ñð!ço’®ÁOÇS[@Ö&ò¨•£“«QÅIAë‚r¢baÅÐØÕ4WX#å‘0šõ¾/£R*²B“å²è–À¢U0vÀK`Ò &ñnnmï|ûÝÞ“ýž®”A~ÏlÚ¬÷1Ö›éjÜDTƒwÍkÙ{ü‰ø;ü¯[}=&(j‰¨§nWP ƒÊ~xÐb•™H—{« ˜ìH˜ÙÞ— FCìPˆJ ¤%±±kÃîPæAô àj}—à,îýê½²1ðcÄàM_‹ ü³Ãáäo‚ z¾ç\ =•´üUwk5‘^°ygÚzøme„¨u™Ç 5ºx¿A•.C)3Ï?yþ:½}q³¢wía¼`à{0Ô3”7!V©nk;ã «V¹U‡õîžZ“@õ2·†{YÿAÍ5»êVÏ7Ö訜ͯN}P¨FdMÒh§ 1¢mªá¡÷•„ƒáj'CÜ@NZ&© `ÂêëÕr7žÛ›þ¥áBêW¨Þ²SäU@‚Ñ•(dBgõœ™jbYµ‘©vq±º¸ÚÛ²Úê’j/Êj+õj *BU»YEõ±Æ(Hª m “_û¯¬Lª3˜«3¨ÖAdÖ÷`êq¯‘[Á]ÉÆ‘ë#Û¬V„s–ŒÇ7F¼õ'ßÀÔY–¼³Ù=iÙÐ,ÑûcWMr5jØc×ÑTâv½IEíŽId-ý[ëª.J{È®9dÉëXÌc·±Ñ³åzȨ5jfÒ;+3¤2¨ í’Nn·ÑŒìÉÄÚC_Ίåàê†É„™=+Î|«mKÜ’ˆŠÄä–xf³D™-O§ÔiWzæ¦L5j™%°‚ÊÇÚ´Š•'®o¦ˆlåîÍcñ·n;»ˆVÌ„B1íu1/]'ZÍtaëØ˜Ù K†å M°šO-‰Ï´¶g-•…¢ºÑÔT4•¢a¥ž²ÿ•Šºl¨óïž:ÇË`¦!9çÇ>ŠÌ(n¥·Ù©0ÜÒ4:BÜo¨ª1ªxÃà®Õ­ÆÃÒc‡ÇAF:øLsn4ö5×ðeÙP;[wkÈ~=5$7ìÎ Ù‰‡†÷˸RÕϵ¨ZøkÊ•(iÞo,Ì9=N«î$ôÀ( ‚¡…(5EA)èL9ÅzáXúùª•Œ<©Z®×Ú-ÝÕî³5BÛë ¢ÒíêÐb¾æ†‘†r‘ýºù jÐu‡|²¨Cz®-)Yq7'«¸»…L©8Yés•*àÌ€?,¸©¸~E³çW”ŽðÖÌV3ùðý@Ý7­Mך<ÿ¶›#˜e½WÊ ík̆æYßz¦ƒ8æá@?Ì7ܰž™†ÚíTÃ¥šCnþ Ý‚ç²Ižhifˆ¢¶Õ1®k[•ªÎ«n£é¦l$J#¤¥,@­|0g)7·ߺUñˆ”Wjµ:ådMÂ:?ù/r*5ïн«ø#5¤îŒKýŸFÊ©R<Ô6á}ô¦†Õ‡©)Ÿqo±÷„Sªm HawWH^×}%B¦â,q‰†Æ}T*¨¢Š?U(ðu×§¨{>…r|Šºßc!7¬®ìá ÎSkb꫸%4£ö;ÜžëÖ:ƉîãöÛ[Ü/§ßd {k¢³ê´jhmˆØÔ{MptÒ6¶Í®ÝÙÆhß°ÊP {Îú$`f|*ü­nQÚ¸~ ”D¦ovÅïʃáïžx7t*²`ØæÅnj™‹®<Ž:U+ô¬b£óð)n£ç+]40E) 6ïœÿïûÿ“¿~ÿ¿·±¹³Uæÿî|ÝÿÿÂöÿ'_óïœÿ[OõÕ&Iý?g¬úÃ=`ƒ\GAm³Ñ¥É~þžd‰¶S%8§¬7#oR¸){ý=°×*÷A®d‰1·©¨žK«>©»ßwñË•lK˜<ø*©¶ætçÿJ"©òÿÔö9ÞÿϽÒÿãz_Ï}~ÿOËÄtþ«ÁçºûK“ØGtÉaÔÓœåu)óªcÞblÄÊq‘[ùš&±44 ¦IœeÁ(ƒ|Æ-+Eþ®© ¦Ä£Ãh1OBéRRP§xÒ‹¡^ýÿ,ç?û;ƒ¾Ñÿ~ŸÎnÂÿWýÿ"ôòEéÿ˜wNOŸŸýôúg“‘k SdoS÷·7*Éûqo‚i1µŽYË%ZÒ!5=h~“北r—õ«º Ý4ˆÀ¼À=îÀuUËC(’WÐ ¡õžâb P ‚9Ú0Õêg´º¥Ì3@{"]LD¡ì.;o£¡d£4¾¿ZyÅÙª{°öÒkhµhÎÉ’òé1^ïÖÝ5Êúô)m]aÊÎŒœ; ÕÇm/ð…)‡rM%Ð"hñe-õ®5•GŸ¹TT†â)TÀ—tqŠ7nÇB')ذ”'Ø*³èG’¶°Š!ùªÐ<ß4-T:pâz²{ëÑ%y|Ä’‰bȾäüTA·¯ÌÈÍJ78ýÃì?®öûŸìý¯Ëì?¸zƒ-öÿ¶ø`‡ü¿Á`ã«ýÿ >Ý‹•FKìà õ«JÁæ~Ð0 ðƒ†YÀYÖ9þ{¥ñx,Ö§`Ö0+Ãܶxvàç?#¢/Vú}ñTŽÒÂMg„ÇŠXÑØÂå˳ƒS±üüùÞÑgÐîìgq´÷üÀÁÆëh^1C¤³9S7'#ÝËÔM&59ûåèøäìðÌéú™8ãÓ_/Æ't·w¯øNŠcøyr(.ÚÇâââ?úø5€Ëö¾ÓÌÏODw+€*ØÓ\§{|¦>LèBMtýDÄ Vº>±®_X×ì—å ,H`$Á.J±Lˆts]”aQVŒ­ZçXtîŽôý5Þ_~>Ñ%#,ÅþLxX้¾÷ñÞ®ôýÞ¤©¾—xç—B]2Ƙlõý%Þ_0è’ß°ä7P[]b¾ÅS¼Å‚·EœK]rŠ%§d3uQŽEy\x<šÞõ‰±?œíŸžœ9Ý&v<}!þùO§+Cu³²b={)VWͳ—ô ø~xîtŸ8“Õõ‹ëUäü…X-ÔÊ~mà×&~má×6~íà×·øõIȳ-€TòÉóµ:ÓЋ“‚¦9¼Ù î:¡éuðÀ4É+ ìkòÆ“ ¾ô:Ÿ)£#´43fôF]§¢t\ÝhNFF#(\žI|˜KßµÇbt, _NäFoø ½ ,à¼d˜Ýq¤fc ûsq~púüðèøÙñO¿8úM¼¨„äÏÑÛu3õžß8Á;ÑÌñeà (²/ЉrZáY Ÿßáê(õvL >Ó=µ˜Î8D¦]9R´@—2’46sˆÖ0'gIùì›TÛÀ´Í²ÇN÷ôŒ¹xx.ú-p»Ì+&Žê0!D6sœNõÆï  n]4hÑi#¨èâ¸éd ¨mc £ä\Ç©O$V\A 1o[ aƒ!p=dào1í›E ràb !yd3¹ž ÷Q±… i“!ñ`$ç±H†Œ‡õsø0@¢Æ¡ýj]»£PT'·2™æäl:P}Šo°vi@ªñІ>ãåNqíÓ¨Kºüâåáþ?ÄÙùÞéyM"‰Þ§›áŒÏVÊè§”ó‡{Kדüöl‚QdÒAÿ:•>îO@!"LÁ}Àþ3ðß@á@#f'{§‡G` dt¤qDõôêŽBɧ¾Ìi1:·Ârxâ¤ç£Ë·§âÉn÷ï¯÷^»âÅîëì‡?hçÚwR½»Hr=uSP°Kz%BºNÇC Öa˜Arp”C1‚ù–" ›#@`Æg÷øõÂ|žt+uÈtòKRX´Æ³¸á„9)d¤P=<ÌÕâgÚ5¸ù±GË—_‡Çb/'È pÕ”/"`f^DDH]ók¼Ž®.#óB^`ë:PýÝ;#‰¯zÆC|Y9:‘ëú@‰À{Î Ù-~‘õ:uûbÊ” {¤–ýçáéñÑóƒ£smð4¾|‚úR‹ «·ƒÿÞ{~òìÀ“:°Ô@êŒ\ïÚÔ¨ØÝ[ƒÕËÐxD–p>Óõ©"ÉEûEBçï.í—ø¾ ÄÄ’Dì2k9'n§¨“þO{oÞßÄ•å÷¿^EáLƒedaÈØCH·{H @ºg>áS–Jv©J¨$ÏLæµ?ç{–»T•’î™_<=ARݺë¹g_§g<Ï Îyž$MmŽlêËã“'µÍª-½’{® +ø&¯tÈi‘!¥DeC‹'Ï\x²Ú·:ÇÉ…dUqAlXVÚbÖLA5X®Ä³Ÿ¨ŸntðÓÎŽÕcÜÁ½+$ÑpŒîíÂîö›.“àBoKqˆì$,âç.Ò‰#;${š!·È,ŠÌ_{íª¢S‚‰Kö¬jΨõÍ›×É!†ôóß+þ]pür*¿â*â‡Î“í×YW½ÓÆ:”ðO¶oèÃïäá°\œú‡[úð˜¶F‘JƒÔ4CC¥Áž5ˆã=åáO¯G'ççÄ*£Q^F0v4‚q~Q6ÃÑSr~ÞÙŽHƒneºtqü´ºBzNQE£>‰U;Pœ.æ Ú·Ø0 -vjæ7?íí¹Óì3€³2ƒ •ò@ÙÂá•]V„ŸfÔb•ÿùÛ§/^žÂF~÷=Ma“ |O@5¶ãxy9l0WDÆéDd öU`ø ^ÓuW“®Ð#çXšÉˆTÐꉠ)žeQ‘žrŽ[£<¤mžN¾Á´Î²qVtþLgY÷E, ý3¾èÐ27ßdã§1SØ“ر8c¥Ù„ƒwI¥”A¯ðAÿözÉtL Í`c–@W0éÈ-Åœf_ˆ©2…íÔ‘F.xQËuVd]žH8ô¾ ͽÆà|Ю ï~Ë6™;8Ð(ƒñëhº®hXh“Ù}) :ž® “®‰ÔÜa1Ä¡äõ¤uÁ[&p1˂طc'Y郎}ªÇ^ŸÍóä¡ä'Òè¥5ÒÛ'‚ºÐ "ÇÄCŠÊ8Ú9Ó–Œ¬Ã ¯Œ¿yÛ£Á ë`(Ҡᙂ¾ý’ÞŽab8z¡1™ÏÒ|¼)@²<Ùŵ€€„†šØáò'p$-À±)x«¹Åïõ*Wi…EÅ´Ó˜+øÐp^Þ:Òex ¤®Š±€ÞF@ìÛ€á­íÏNÁp[úín1g¶ì©V”¡òê^ Èm7¹®Íɳž.$á{Ã…u*䆃cf²Ã uß;ðõj÷£Ùm§µNO0VôÜ×ïÚ>õ~FÌ£A;®‚ÑÀŽS©l›†Ä­¯¦K,xJÌR?òØ\ø ¹éUÙ“ÈÚ¸QÆ&mÜu4aÄ7nƒ?•*¾¼’óÓ1u°Ý_¿«LÚ‚[@ÓŸú–ሑC[u¸0pp䪞óDîK*b—P]¢¯9ƒ.óŠ<ø®°ÅsÙ\¤ÅÜ]ÝhÝŠêofoé¦Z9óí’¾žßÈÙH‚q*S)/ W\Ѩý8ÏZPó \k'¼¿=ÆÖ4îÿáÂåÂë ÃÓl~Ô; ЋF„f ®O®çSL«u.Wu§Dp_ogNeè¯ã°/“·ì" ¥4^t!ê^Å<Ïxź Šó\14{ p$P\>ÉÇél|‰kîœ'$²qåb^j”ITu–l¨ ˤ ÞÐÎÒ Mêj£(úêÄ´ÆL +¶Ómƒ'ž•‹iíÔÁDÙèp|€à=Y«jxÛÍ«C«vn%Æö/YÛðÅu›'#×FÐãHS4ï«ÐkÚ¹=ir,l3 -é4Ÿk2q<Ûê´)P¨•òœiRCE­«ÒqäÏÚ5š½?é´·ñYýzN'„êìH…v÷ÒÍŠiQlicÚ& ¨†m°ÞÒnœÿ`1ãúF²]Ç2\QK“¦ŽN„ue¢ô¾Ãáê;q¦¾¹šº•uµ$½ŽÊìÂW-ÝíN¨<ò]©ŠAúR0yñ·b€ ¸‰H‹íü*óÃ.Ķ IK]T6 o¿ÞízÆ‘~)ÅðÏìˆ0®›ˆzC%ÝxôêmÎä£SèDSè%~õ\¶–ñ «™H³ÂžH´Oø¨¾Húí¡þû,Qs W°VAjXαR2Š=tReã÷Ì‚¿|–ì³ »==b³7ïæ;]JÇÝŽ|[v©±ÛDŠŸŽ“ûšÿ(³ê’Š_R:vÔÇãt–g#"ÎìÌòS“¾lšm>0\ÐT1OóʺòTåuüTaÓU×´×;ß7gªÞ(Ãi[ÌDkWbÊ—¬ÀwÌmZ –z–ÎlÆ'Þyì„>ˆ `°á1‰zïÂÂùnA· ØÙ>ìre´›7»*‰1Àê»âÃ<`6×D6l 3uxGgÙ 55}s”Y³âGo àK‰ŸL]h‹Æ2nùy÷Z’zÚàQo¼(¦þC¢.·ÌAg^Þre5²ŸˆGg-Zë̯lΟâjÁ=t60Ú<ÞâòmÊ^4©†ÿº°*€³KÃÇ<±™¸M`þ­ïÔ’C;2—ÿânsjÓšý)6ž‹| ÷´yÙ ´ÍUùa¾ûÐa:Aìh‹¶E|)Ž£«jËæË®ù˜ÕŽIòŸ7qÒžÿM~F‹ÓËVã$O²ªÍï2J/_à½ÀdŠAÏX‰O€‘B³îL­D5: ãjÜÊòÕ*š ’º]P{ÖL©`¦ÒïsÓ§w{bRÇÙh3/¢)Å7 RÚ(Ç|ÅX5«;ü9ÚïYùS>¡–É Øvm;rá‹&(UcòëFmq%‰üü8w~æ™ýjGz7¨ó eøéñê€ù¨š/ù¢ÂZ/Üùò2=5¢Eߨ§•¾›(–Í-ý·3†›˜âH.~“Iï>ܽv’œÃ˜'/àÎ7jpc“x¥‘hÑAŠ–¡ýÈú¯¤1“=¯ê±tÌV¥pdeRU:2rëHBhÚÍ ø%eŽmKÇUiÝMŠWFÅÁªé¥œò¢ÔËŠÕ2÷Xwà ?z OŸµ#ZÝ‹(mBOKVC8lX½;µ¯›û3!9e}ãL’÷&ˆàU ”Ý´º`Æ(4”Nk¦ý^>Vg…stàÓõì#»ÚIÀ5šæPXÑ,‡ª¥E€ÉÌ9K `87`x× 3u 0…mS_Õ4xâp*ʼnwƒãÚ ³ÓÎg -K傤X6µ*x`Îóq› E”ÞÁíï0vÓ3(Ã9×n§š2”†{‘‘vjùuœ]é:Þ^w/ÌYÁï{Åû®^úv ÞM|‡?ì®ìäpÕÄݸ‚Þó˯`'²)9=pÛÅ«6»xÞ}û—\¼Æ±¿äcG$Ÿ9Ñ®&»*qÓúNèÊ_i%š9½LtuZ‰ŒÏÿô´#.Ó`<¾©s Á}?Ú“—›»n÷縻¥]ðÒ$¨‹û¶4WƒVeÕD€%/Ejvá[£˜L5=u,À¡¶¢Ï¢%]\iIŸ}Q[“2*ž»$1m6Ç™×9 äã ê§aþ^?=žÍôÇÆèg„ Ê'އÑÏ9 ö™MÀò‘`ä£ðÁòYb`Þ‡#`¼Š{ü©Ò¦«“žr $=&cËýÞì7ŽÛ¸£S>qò”#ô0ƒ·%ú±ÃL‰5ÉŠ×ã#Ú^5—¤Ú›ýÎöñ`¾… s9}3 ‹.YôDô2nï2“’nÎKÖ`•ãò gUÕ?özK‚'jKé¨u>+!¶q棘6¹K6à-GX–ßq¯ìãÀ (ûUÛlèØ}eC#˜lJ‹LÀ;¥dSoÔ™a³¥“òä#æ'GßtS˜~‰GÅ)ÄÞÃÎAÓý¨iκã0†^©ÂœÀBØâå="ØSI-Î7`êNç0+d’Š}ŸŸ$ÛHú¿ß%")\Sóÿ‹2D%Y» 9u)!O‡0» }©~–'º¹"‰iJŠ©ž±¾5}í%Ûþ˜·¡x~Ûé›î¥êÍ*S² Þ Ùfwe¯½Pmò‰¦Sn‘õCÔ’]Ÿ«®Æ‡Nm#ñÝÕœ¹ ³€ˆ¬ÐWÝœ<\¾„Œ— у~ü]—Q·Ä ˆ§Ó̇Çý8Û’‘F<¢ý8ôG1•p¯­ó瞉êC"¨b81„yÀnåºÊÇÒ g1ÉR(WÓ· jÚK‘Ò^^07QgNÜÅMîâŒ'!–~yü]·‘íSð~óáSƒó²¬ŒLNé¤ÞÂÐÄ@dÅõîA%ªìç˜4½„IM‹{ÑH‹—¸(;Õ”$pÀÓÓ\H€G_Q°[ÚQ§‚‹†1ÏÊO²Ù™a T¦ÉZy¨%‰èAå'ŽvX©sfi™F§1ØIQ‚ÜŽ4ؾ^´CWb1Ëjù£nÙ´(ü]§¥7G›×ÀvÎÇÏ\Dpüü=<þÈ"Äå1Nˆ<ªö5t:øÞW-]ØOAÐܼNêY~|¸Ä0­Ù¼ß5ÁûG^Ç ûåÙeÝw›Ž_òQ®¹/žÂéý–œMWŽÙÂ9ò¥v¯YÊ•›ì9Õí@bwÖSW4½°ðî+$qV­.couµˆèc^6GEûeÛPû«pTjd%Oé´:ŽyÅÒV-°w< ÇöSñàbΪâàÊT܌ؠãvPÀAAX3ôÚP¹‚µÌŒÚiYòÀ9)üI‘‰š~L¸j\ã ¾özÏœöÒátüìwÓp/Ùv34jBâU2,/ 3ß:ñ42cözŽ3ÜæÏ;¥cMöfTKhÇWŠãÔ ç<·@(Áô\)P} X¨”…q**¾ëNˆ×"ÉC±R»ª§±¢y¤`û9‡Rò d ÆÄ 8Al¿»jbÅ4%H¢ÜÐa`¾ðا „¼¡¡µE›ùÌE Æ&•žÓ*w®(!|#ðÝpV#míIHfû{ OÛVÆQaAÌrÄýæ’h»Á[è®»À²pýÍØòW’0úÏ´(Ùø«Ld”oa½5lèí–suÆNÉ®!=h´¥ÈÀU'ReÀt… ?˜º±òs¹ _Ð7O•èS"EAÆ!tS eO‡ífWPßèuå'zñoÏÄÓè°~çïâáBlØ—¼{–:'^O«­Åâ#k'Õ0…GšÌµ›m½.ÙïÖn×íº„Q¶Ï³ÎPl0EénÉë¶y?±Nì¥wy-’í£® ¡ÀõV‘ ÿí÷O¢¥ÑøIíˆùB¶¸]ôém½Çivf‘l~¢"¯ÀxÄB4ä¨w¢[•n _ÚÇ×úT!«çðlwëü+B•–ÝDkÌ_ªL¦aëÌL§ƒ·錯ӔØbI9×× HbÇZž8½‰%8 Wz¨„5o2§mwÂ^Àô¨KT-‚^”óF6˜øó EE¯IÜBi;©›‹‰ó¦xŽ3¶0cCG»ÍÁüµ>Õmœø“eÝïÄÁ<¡#­µeîåùB„]uKC€» &ïó ªI\x·ê`ËŸÅ¡ÁŽ˜kI¹íQ™KûäÝÚà@B æÙS™íÒrò {Â2ynÞ—„H…q q]§%ƒÔbæ’¥v;½Že«yhÃbyÇ¿d6©]år‹ÎÏF·c­ ÎE@M‹+DÒvâqK{Év´ Aìª&ºxªjÀf;žÙÙ”Æ? \Í6¹ù,-*DgÃŽ$±t!MUMQ£ˆ,¶§+»[‡™e*óö _þé¥Å«Ô±Lä–T™5}LhËŸc|ÆÆq\€è«3yï=]µD¥H2ÕôRãÛ|wk½O@Çù$ìà÷z½Úx©ÒJ9EÒÑ’Å^‘1` ·œ!ª³˜Ó6m˜³!:¼1,’ —8F®5`CBø8ÎvòÌ~Ä‚Ø eY+»‘[R´FX[&º6%PÃΪ´jI-K™å²5Ï/ss¼ÍÈ9>‹kßS» _Í }Êã‘“g*)k¹•¦§Ifâögéüêbÿ|9dã†iÄ•¹4zë<—ŒXïÄ V¿Rt@Ÿ9 &Ôš Á†…š‘mkf^]à”7_'Í9´Ú¬³Ÿx$»¼uBÕ°¸›]ý%ç@–—Ogå[¶€Zº$[Òñëª%N;xJŽfÈ3‹ÓÝXÆqC ƒGTŠjc¹H½Šß ÷l ›ÌÆRJR*úd´¦|Eä Ó]ðObg|Ò9ôBßëÝh^ïÖ¤>‡“¼öh/^a”3.*$*›ÅT"Âà;ŽÌ$n‘σEvÚÆ B+¹±Eʪlö^-MP†"~°¤t›ï_^]*½ºà1àQ–H烮f‘m‡å¨EÖ÷åµÓÕÙÉÔWœkD+ß±«-¹+âo+§Ü÷Ö„m¦Ðñ»¤[¹¥h4?”f4¹ft‡$clT—#_¹&ÐR*ar¦\ѧU"t˜Ô©£èVŽó6Á(£{ÝB½©!ksÒªãˆt…~äœLe°l1_&.‹£B뜤]útšÉjópi{®0rKÞ7‹h3ô>U‹‰¥Þ-èÔöûä÷Á4.¶­u‡Ö/¸—ÝÖx:wεæ®3Èôj‘a™iÙ63òK‚0]Ìj]©ncÒ€·eÌ;”æ¥Uun“»2$âî„D¼K×Y*S.¾mX7æb¾™@E·€½ N APN6_”cúó0!gl[{—;*wÖÍMn±D“ÀGÐÄ·‹hÇ,Óæ„žš Lüšeg)và7Á·†CšWp)*·Ì_N•¹ËDä,^\/ùâls*‚°Ž3ù0O®·!Ü=!Ì¢¾8[ÐLlW»ÞXzõ¢uœàõ+çpÌǹn h¹n— ¶’ïs2K€Éùº¼GXo’ý7øE¹gÈO§ e„E!Ê¿ì$”ênØØ¨Â;àêÇõ1[óЦÅ\òÂ;×q3 ó-(/%z–t~ƒ÷§£Ê7!Þq]«Îã\^–‡Í¬r³ª$ÇZ'A¦ ¹-¯ÝCÔ}iR tD ³ñŽÚqx)ÌŠzZâNÙn†³jÊ ƒÌŽ¥E.ÁäNMg)p)Ç9å‚:Vc;\8õé(q9f—¹¸lðù7‹fYÖ©Îh1ÏÇœÔѵ^ÍnVêNʪAßdÀ>2æ©hï‡%ç8(Ô·›nt6`زы&ƒw9âQåo/XØ5! _~!^ywÚé¿§èßA•I1F&·¿Øø(]=ÒeGé÷4:R¿8×ÀŽ´~”~ƒ#­¥kT;Òð(]›ú‘ÖŽÒµk9RHKnóW)ÍÞ·[r¤®Ax´+wyùÑvú¾I¶€On±õÏÐ5i¹–ÿ¬gèk¿–›žá&×ò#áK³«QEFæL™SK¤Ž¨*ƒZHõ]Z¨êNæ\ùñGWbÓjDÀN¶+u¼À@²¹{*sJæs0|!‰¹fïÊsþø·~箽E<6¤LÓIŸÑEõtâ„ÀÒ[Oô朞lÞàœºêeé÷+•„Å¡<*šv9®hõ:/ìº4Õ¤æt¹+1:_ˆlR$æ'w9Í:Â~íì€ù"Žze5²8ëö¡€Do¶M°qÙ‰ÒdÑäz‰ ‰íðu"=v´GìM7шAKÞŒöaÍÚȲm|ÓgfüB×Iä“]ZË®x‰Mó\Hœ9 ¬¯4 WfXTY—39‘ü°µ°ò½Ý/OÍŸêæñïà­ÍX8T| ÞÙŒ‘«½Ôdç½.gêjM×°vÍÖK¼ZÓõl^í…5Ì^­õ¦,_íµuŒš/aîÖ„OœæhU‰Ã™lpì~Yñ»ËØ…v6!~wÙA·m}ÎK¿ÖÃM®x¼þ@›{µæˆãm¯½ÛrÆ«+GÛñ?Y¾I£_éÖ׿¹s«øFÆK+aÂÁÀÕïû¼l\‚Í âC ¡öÒò•óÿ/CÁ²®€óíØÛÞm…ÚÙ'KÆ]M h›s\4!¡uÜÈb5hßqÀ/Áɇ†Ö«³í¿*ñß Œæ{ ­à¹!$´¾»!@´_åÍà¢õÝ Á£õÝ ¡¤}ΛK’|8Ì´¿»èlA?¶ƒO?è[Z„äðÍH.'!L¬`$[áÃ儘<,».2õøäë{þ+2’?ŽWÀ@Ò„ÇÜ.#Q›' Áƒ)!½*9~×ÐK°7, .<`lˆB® KʽÈá±GM.$†•ˆÉôðÑÌ`ÔPF05Üð‘8‰6•Á3$I‚¹ñÊæ5¦~ÿ¢ÕÔ®[]c"ŠÿVŒâ¿ÌGñߦƤÆ[ëMKñß Mñߦf§øo [ºlŒe¦©øïj†ªÃœßÞú0h[eØ:bxÛÌòÿ­µƒÔ6q«Hü·‰$þÛÄbÒ<Û5ö“Ú)4h[±Ž ,-ñß hkCgÉþÕXrpe;vr{5jº³)Bº{4ôé¦È糫¡œÏ¯€h¾ø÷þÞ/@_L÷j,ʆçžitÖ±§Í3½lÆœ6®ýd#góï&*³ÜÙEÀ²–%]rY?K®Æ^¬¼ŒGôÑaEOV_L´¸âÅÄ++‘or1ÑpÓ‹y¼õl“ƒ=ºÊõ<Úør­¥üGëTÖW¡ë[«Ïy饌àŸmý<£æh¢ö|¶m´øh£+Ë>–þ•Í.ìœhðʆ7Yzq×]Û+_Ú•Wvà »ñueôÿ™k:ÜZ}¬¿Åa®¸£W»¡W>Ìÿ{÷ò„ô­?Á~ðÂA¡œë1|çv?y¼ù9~R‚žîôqB+®fÐönÕi†½~ÚOŽ7¿Ÿ¬—¦ÃÎ?ë'_mÈ冯}ÞOž~à=½ýÙtÿöð|k³£Ž×õçwp5 ˆßý¨¿½)xÄo] VâW×1ÕŸ˜2ç§¶1Eqa‹[;›þÝúgñ j1­Ðõ®Ò{G Úäïc¼ój­Uû‡öwVZ¯ÚÞÙ@6l{mÙ¢íu?|„­ûµ©Zƺ¥X‚¯ï̶®vÑ6¹_mÛ²\©ÑhºÒf»é½k9—W8ö_ÐtéjƒÕV%Kû jåÛ›.¹hmM[¹ÉåW¸vý–Ýöqó6¿p›››®äæv•[¸ÊnI×/ûýþý~©~Ù¥ú¿wSÚXÀ¿–YòlA$´Yåp”ü5-2bY³–GGË>'(ý„hÎQnùsi»G‹B2@W$r”þN¡4¯þ´òÍ—’(’ßæt(„-Æ=ìCŸ×Û‹¢$ï‡î¾•PV¿ÉŠgËYÆ ì½ÛZ·áíxë>¬Üí¨]ëÎÿg°áÖûíÁ´o½k³îZ(ÂÞ»ìcÃo¿ù+·üŸf£ó­‚Y¿ëÿ4Èæ78ˆì#Äo³ãíóo¸§mÔÉahv祄ƒÍ¤dç¾(ƒ®‰øjFäÉFn¸˜0Ä^ÎçiÆ¥ýdOn¼GF¤J?G‡’†¤BÆE¢ù¯ª|ðÃRþÞÙÖ&Ú×ÖOPfæ^X6Ãx‚-^„{gƒø$k³lç„΋ôßK¾I‘”¼ñóÍä¸H‰Õ«ò´õéQò—!{×¢_é7z-üM~I®ó8þÁ3Äþf¨ò»8•ôÅÉ$Ó\ãyñ±åRžã»›÷n& ¶#XÝÚåm¾Ðõ‹^½Ë·â÷¢íhÓÉàˆS8ZÒ䇑ljÓY>Ig9ç|&A¢I>?_åÐNÔ½¬æ—"ºR_qCɃz-4Ãi9åÔˆñù,E¥Û;û<4r !—x?z=î뇷âVL‘|/ÏQ€«äÜU³Í7Ï99 î$¯Pí+٢߷§¸š’¤kÃúò~ªY—–BàÃÃþ›ã7)ÝýÓ‚Úô(âܹ|Ô£¨½ð‘Î%nekßÖø…•§Ä]Äí7?¦I^<~œ?yñ4È(Ж~öä䛓—Ç’ÂYc›}JUM ßš†””È>€ˆd¢®ZÜÏ…”×éæ n ­ï¬ îk$DO¸Töð6*°ô“a~–ÏrŒ:~>‡A‰A-gÉiÙ\:˜ËNI0üëït<„xsú”ëÄ"°O]©•Ѳ&ÁoN\&욬›ø<¨k*“è,‘ Aé‹yTTÓå&ަÍzú…ÇÅ÷¨ Jkç…à¯ô}™*˜[X¿ä÷E§·‰¼âÐ⌒ M2 Œ¶Ô‹óóY¹8;wI*À¼uµRsK­RºeÄ[^JZU”RÆ<Ïiî—œP5€ZË7³þk&JUYK$Æ~ß§_yÑûË‘³Óž•ZÇõ"Eq™*§ì⨳2ÌÜ‘[ hk:AÆ1NY…Ä \ÇI2 æså{%“q‡+5Óù,fÙ$J˜”ZlÉ^í'© ˜¶OD+‚ÜñÅ0¯¦„K‘‹…°ƒo‹*R”ÍV”°•€p’|É(*’튻‰þ½½Ÿ<Ì´\RnÞ‰šßÝCóý}bRNÑüSÎsº8«,á)&ã‹J2p¹cT´ÔéÑ­™3.ZDûº ½ ‰Øâ9 Ž0¬×¯¸Z‹TMšÏÁµ*+>KZ À2¸}N îPIQZù¼j›C×q7Ÿ#ï9¡±mWº—ÎÀCŒÔìCëy¹Ks¢—:¾ù(Í‘_K’¡à«KÄåGùÙBê9¢ÒíyAdfHøå$+Âx€î á.Š#å„è'=­¦#à'ãzzùªr,öÆsDHÒùà\¨5“à·•&M'zÃQz%+0"½ƒAù„y3ä'â\Y7Åà?JÝò—žk5¨ò”ÆÍærÇÍgÔõðû?»œ²'42ÉQZ;ңߘ8aZŒÂ&Þ¦gÀ.OG—4,>ÅÆ÷ä„z¸¤eÐ Ã%WðL_,©m&#Êr¦eebHê2—¦ÇÆ5½ÐCµ8C*uA:S™s…œUJàç¥Ï·LSDý\º^Ð<¼3M§@dõ÷BôxH3û¦Ÿ<‚Ý„œÎ#âUò°ü‰®ÛþÝÎßÓ ÉœÎçû"ç9¿ì<%@y8+K0 ôYt`OÊ*}ó4ùôöþí½Ý;ŸñEçûÇ>ï($À„ÜWNŠÍrKÔzAZ™µ¶´\1ì´Ö/EúPŸ¼Ø†ËæîrMõ\áyÖúb’ –n†Oz5N¹ L€±@‘õê=m£6­VôwÂCéÜïåù|>½wëÖÅÅE?<Š[ÿC‡s‹:¹åÖï³©Š WPe†·™Ý#%¹öM¸'ñgPþ²ŠePf,"ф߳æškSr9#Ö üîÿ÷ëøÿÑ‘îßÝ»MÃà¿ÒßÞþÞÞ§{{ØÛÛ¿³ÿî}ö©üKŸîzû³?Ð?{wïÞÞûôÓÏÐîöí}ú÷¿Áßh›†$ø^Ù®š/P|nù"éïàö]]ÔÁþ—üÝZO­LÔ+4eƒè舛 ~TN/…aǽe“ßë¨YÛ·‹XAÿ;þöÅIòˆð8g<ë|bxuK ÷Ï·è9É¢«Ò¶•Íf“ꌞò‹þµÓxay«ù2±³Qÿü¨öšñþôb0 4ÏKjý„Œžõß4¿{ðÛ9 ñSç“ñð#”^}Òù„>*àK²½Íê¢n²×Ũ#4ûêé·/¿~þø±k d{:Ÿu;Ÿ‰$)µÓ©@R‘5œÉŽ~á|ã´1Éagëu±ÕÙzjå³E¡yäÿpr‹šG~qÕW ¢^³Ëz‚Î¥´Ó»îÈqÉ\—/»xÏ?æqô¹qk´ð ãž>€Â÷ˆ•€sÖˆ¹ ¨NCõûðA9=z@ uá_‚‡·nÞÚõŽÊ›æ€xÜã±-ßh^¨xÌÉ”CÓpK«²Üæ(ËŽL› ;x@"õ‘„§sÁ$¢ªZÚ¥í|žŽóÿ̆õqƒ½ ;+[p•å ó÷üÊ‚9Ÿ¡“-Xʶd£3÷™ßæ¡Sørå2ÍÆ}üàñlv$Ii‰Z»<ýÌŠ“ð-~×6 /?^]a¡Ù®KC‚oÒ¨ËC:h?!æn´o6äèÁ(—ãP]„×9popyÔBnì°Z²!oóiròìF•ìSý'¸Ù°gXp”¬VÓÖ!   ¦t¤j;€€TÞlØüWÉ¥aÏ1šå¤Uõ!€“îˆÇ>Ûud×ÌTQ§ûãø"YêˆÑe >á±f¤ü05ÉGVü‰V‰°bÆŽ5~€ä¿G`ƒ‚Ʈޙ*ß¹ÈBcg]g]ãN´ñ ßéÎ%š|7®ä¬‚<Z=ìtdõb?|[ƒ<Zßq®7¯€HˆäÔ0ÎÈb_>x™ž âaö¼œVªy–'ƒr¼!= •S”‚øŠ¹ó²ÜåÒ˜ŒyÜ ¿•“ô'«`Á²™_øfãÎp±±#d-yTÆg£¹'¬/²Ì {‰PÝþ~² }„ñLµ¼¬¯Ë a< f¸.îw˜MzÁ5!Ø<2 5ŵ }0-Ýh¤ï1;<Å¢PÍ'ó ãÑ8={3¿ïŸkqeô„¾“ÿ¢Ýࢣɴ—T÷MîxÕPÓ;Éq.G¬¯w×%Yüõ"U|T\/K¦½ácÃÓ6êÅÕ# ŒPèÃ*Vïû^tÝ þÁ¢¨Ç­øåªÐ§Ù¸¼èöÛÜŽy gƒûÁ\$ õTÊ)Õç£íp“¡^~v[}ŸúkÌH`"½ö¥>19шó³=yóðéW'O¿x‘À.«+klB²jKéïÉ›“oÿvÂi|QÒÝœXQóf?Ë»ùúäù‹—ÒÍéæk6‚Š>dĦžýݼøþÙãç_s7ŸËq½¨Qã~4Ç1ç•íú6ö¯›l'òa÷ˆÏ>¹žìw]kµŠÉ’µÞ®·>è&×Á¤Gï°ewé;wšïä•°Kßù¼íAäöNcmׯ»ÅÍÉáar#¹Ñõ2Ðã0?›CϲͰ;è2Ì=—²U¾b:kš²JÊŠÖRléÉ€¯ëî>Hã Ñ∩<ä¾…Â&ˆ5žŽpkoÿàö»Ÿ~öù[÷á\Dm_tµjuŸ~œRKÂFƒóÙ¶¼Ùtñ»6¢çÉŸðß]ë8¹—ð«¿gj1f%ó¥½6 ö7önxlSþ´$¥Ô ƹ]Åìäj±û»Mì¦xT²#a=·ubIõušóò,c½»E¨p «ªä¢_Äø¥—ZÌ—UjÖ W+кÉ\ŸÔNòÕà_øü4+w¾¢t;@ã2‹ࣿ?óÍñ¿õ7 ü9&:"‚Ãl°ž8ÇÞÌéä ®GeA”}^EÕ6•b”LpØm!ÑJ·j+¦^ÙŠd ·yI*5rÏPžÜˆ…@S¤ºœl?ŸM¸\ƒ–dÓ^öÅÍd§ª®Ö wí– ïƒ}üê•ê É=‹Ý×Î…Þzñ ¼L_ÔeÐËô·t\¦~{ø1¦q¸lØë‚® 1©C†ý!}q×|§â;ƒ 6L>±{ ÷dX2—ErD4coÏ7Ú»ÏÑýþÝã"¹‰A˜Ë‹F¹ySÆù'[Ú}íuy¬î0)ø³=€%V}L¡ãIggÛ5B?@AMaŸUSÐKT9”ì@´å/î7[ÄÍøA²Ã¬©þ¨Ó¾Ûgåå›ÐóžîõÎTX{Jüª}dæÒ¾`:ö™rûHâ3乑Lk¿³´i_F€HùȲ™}aÒd_€n|W-ì /ξ{lߘií%¢2{3×.òö¦rfÎla…6øvñq¨Ó‰˜{¹ t¥ê{¶O |+ÝBr¦Üg5¼©ˆ[§KÑOôX%ë¦*›zï1M$FvâQuq.hÔÑSƒ.w`¦6´²”Ûj!RUú GPJÿ½¯œɂȎ\K{””ƒûvõÄe©ƒ¯÷n8š¶ÃÒ»7ºÉܹ͛‘;¶Ét›÷“p[Ý®^FÝ’Ãd_îš\¾_í¯ëªÃl#Vuâ¦÷ðFòßÿ¸¯Ïâ¯ßÝH¬_Ñ¢&Iø*Ȱ»|±'±lxÐ/“ìàJFmé”ÃAwn%‰¿§ô\¢ûhX‹ß VéÆ!õNPâ~¸Yÿ§pV³.º>Ôfu(HûJ¸nßnJ×'ímCø7þó»yHÃP¿Uu‘N·€ô¥ûúÉÁY|7õt8Œ^éEãë›ÑFíòF *q™[ù2ÔǶÀhF?/ƒ¼bòÈótÀeð§´ŸAðzÑmÙ[¡*ÁÍVRàÖ¢XÓ~å‘Ácmß¿oã)I©Í%®yCü¨×Jb'YqåIØîþý¶ùsG«V #Ð^ŸóÅÐ/ÓðË솃cÿc¶x~¹¸Ñ@n®àÛ…Ä“0aÞ£«S€ÅÝo@‘›¼èöÙ6ºÙt¦M…´5Ǹ½ìÅJ_T1Õ/µ)ȤmŸ7`Úm Ú£ñâg_„@Ë/[ x›`>ÇÝ Àsã„›pz£«ô›§½tnG´=YÝnÈíˆð¯i÷˜ÛO°¦]Æí˜aXÙnÄ툗XÓß·cFce»œÛ1²²ÝÜŽ¥¡•íÆÜŽu¢+Û½ãv¢L\Õî9·~gU»9·cN¨Ù_>~6¬dè±#O9t§b¥ãh[-Qâ‡$€¿t/ùcŠGÇoUùf$îJ,”°Œ€Cz°Å›ìÀ©™{àŒ^ng‡¹(ð´Ž‘aŽ%bx#>§•ñuìkÀ[*ÿØÊ$>§Ù¨ýC½¨æCâ ÉDÉã§_³~@¾¥A![ÖÉI ?'Õ,A"Mñ¯`›<•ØI„<ï(ï_s]EïOÕ¹ùÍ—…椗œ zøI7š¤ÔÄs]Yú5³(² kÙϺjŒK ¨éZR¶ûîªc7{L³èO¢¯ã•ƒ®À÷¾Ï‡ ’ˆyï{,7³c²¨?ó™›Rçò˜µê4Vû^Y/âŽ$*xZé¼v$&•rð@æXƒEÁÚEñÊLm"Ë­¥ß‰•ŠÌVÏÜu¥<:«62‰-:ãwf‘Î Ó§÷…ÔÁrÀÅþæ~ÛK¯IQ¥8_™Êtèp“-D“î\Ò{ò‘Ú_ "h$tŒòlÌ’¼º÷î|LEºí…n'~ª{]Yƒ¯¯gX[M@!N˜NðוÀ»Ï$+ñÊ…ÂGÁÝ`OÔ°Ön»ë¨ÂÕü†ètà§ÈÇ ¤1Õ ;(H+’ól?Y“¨Äß‚d%ú@È Oi‰ãøÛÔ5j@{?™"û_ÅžÄÉÈ¡¼«à Lç5ÊGÑt¼Ì‘ðŸ;‰ Ríθp#‹ñ˜ˆHFñ ß7™wÓ¬º$;4Fоrÿ t™%þó>l·#í×äî=ÿ÷0ù/LYþ‡¹$?ÓÄ—=2õ¥[0¯}\Èů ÌIüU›%Ió"Ÿçbúï'^ùRÃdÂçâgËBh ž»ÄiÏÔ{TôN3 ìöºÈKÖ_3JOg»SJHÂ"è>]Ìˉèw¬(fÝhÀFôåžÚ¥ºß.RèÙVãìœçômƒÄ–"¦Íº‘øÆò–~2?³[ðbʧ¶ª§dçj}M—uf°q…îL â;B ½:ô·„’Ž/¦ÓOgóÛ¡è ö‡ht$¹7^±T²Í#ùŸ§^·=&úN®LÂþŒ1OàJ„d²3‚|¥7²&S¯ÝL6‰ã¾ Êé%:¬¤Ç«÷‚&LÂ5ñÞÚE÷kº yrý:IØ“ NIÛŠ6ÕD·öÒÍ›Ü$ø™Á}ç÷ÊjŸP軞ÆÝ¢«iÐCö>ß {ªr²Ìø{FÓæo¯v÷0{P²»+“ð) ;h ÷&˜80c,ÆF÷놺)I]n«J|sè“~Ùî”ÓÆ{´¾ý§œF{È3Úæ—ÂN]¯ÝnÔ¿ ’ Œ`žZÐîʧn¼.{ɵl>E˜&õMv8¿Ž?€Â•¨ABåô+Ôu»pÀõ¤¶›ü?9ʉ®ì݇—o/§F뽩××B¶_o}9ár‰…ð¹= }Ä‹áã²Óu{ÅKÜïl:ßµsý9²ÇD¼ÒfœÏÚÖr=k{XwG7›‚¿Ÿ›ÜÎ5}ò–Õæe¢ÙUxl/ ø’i]OWÉ-è!ê ãZß³ƒ–ûYºŽ[ð”'=–_Üs~˜QxÆËÔìÞô#„ÝŽuk¼›tRÇ,ï‹pÚoP8=ëîg›a!ÓÇ›õ{÷ã{þÕÛñ¹÷¦-_3x±ó^Ýž¯_vTÒöˆCCS{Øø¡9ð6öéL ÞÊYñ{Þd/êKu3®" ‘¸ PŸ‹)K¼‹9«D$~ƒã¡eB}Óšü“/IÊGÍ×4Œ™Ï'Fú¦~ŒA¡q?ÝExq²¿!²K€¹æµ8Í2$'•¡m×)‡#ü7Â<'û‰M<™@5eïœ ±Ÿ,5‡#¸µÇç@ÿEPla?…§È>þs`­BuŠöîß>`À‘ÀÙC=@˜°¾»}áß›XŒÁ Žºš1;X•kÒ¯?†,pÍ W¼AÝàe¾xJùåTn²HÍ?=°]dq,‘D8ÚfODÿÀ–çW`RÒ¾ô&2Ñ> EÓƒ ‰Cû‡¦ze•ý߯¨ß ?‘*éãQ0hBj¶»K ®©[`+ëÂlQp˜áL |°wÀH2¶ â"»²pôÜN¢ÒâÒÅ/° º¨œ?›q‡ŠâºÞ^ÞÞ@´K‚øðÌ÷ý¿-nà~øJ2†FýŽi8ìUs]ŠøO½'v'’à Ès¯¼Ç×ùãõŠybÝÃÙ20O‚Æ¿:Ïâ—höƒq?xÍ¿6ý€ôí()hP=¡À!Êž¶ñpüu,šÃÝngÊžñN@ÆaP«kQm_S7 ¨‚ðºüæX€pדÿ©/2`Iêêjš =Äúƒuݯь­‹EQÄñ~ĘK#“àœ BÐefÌôJ8G瘆w¸Cظ«¡)€§uÓo›Ð2I(ZÚÝ×Iˆƒ£]t ³&!ï^r‹dF(˜õ+2oÞ´7{úYÛh#£nÜÂ5õ—SI_Q$Ü\Ò¸]ŽJ—¢¯5§Õî_KCn„jï®>cÁ™ô˶ æ¯hYŽC¸_÷È×fq+ü+µÝÍúü®ºuh¦´„Ì$+˜qW° ìëRYáøQ-6LCÕ9E¡oÎùÚ"wÓì²Ôl:.ÄÖíÃØ Çœ"œ$/WÀÙ£ò‘ÌV0‹ÄPÌ"'0E¦a…›‰‡‚Xñ~åñ¨,{n@YŽ Iú´•\Oäßáb2¹4’BߊŤ—Lè¿Þ–¼L—Š%CÝÁ†iK¡Q6\0#O –&šŽig':þu7û_oއ B”Iô<)eéIí®-dKùxÞËS˪ˆ|¢Ã¼8ÿ¶.UN!X†ëÁöÄlM{Ã5iÓ•÷c:i»[ëlßè×ÏIíV´i þ²[W‘-j·»·\äXïèƒp¼4"Þˆ.ú&¹XšQÕ°#ÎÉ‚ft-ªòëy>ÝEuqxq‘œ<ë'®ûA9e]mÖ·õ•†8§+ ²‰Ä™UîjìÖEëV-㨠dŸÌ<Ç8+²dã\K0µû-U¤'^ÍÉÈ\Üè™ßUçî#¾½ª$’m¯§.:ÔÉ3£t1žk$)Id[òQ.áy[ê¾·Õ_kèbÛ$y&ý~=¾”ñ 7yš`ׯñcÛÎ/þA²Çá-¶(vç@é刡Åq¦ … ;ï› ªË¥ qêªKŒh|'&Û˜úJ×A×—}7ØW%ÒjNCW”¤î0bHGÙa1ùï¸ I„ åÕ‚-êj‘þÂ^øµíÑ`žŒÅ +è)Ø\íIYÚ4"ÒӨŤà½Õ-Z-'ˆ(§Gr£Ô9åË… œƒb€y•GýXù¾ÒW‘DàâŒÝNLA?be^'¶Åˆ…EM3X* ¹Ã·YÖž Ú‘/=yßuWC½Æá颽è ïª5‹ÙÝï%.Öc¯—¸ð z 0»/§ °xœÏ”å „9Hiþ^> P?H$>:Cº#1üQ¼ ø#Gð'fÖø“ø óGçÀïúW} àQµÍÿ4}kKá¸Õ_e¡~¤åE¦Ÿà*J°Ò1ª¢?¸æÝ<Ãø4ï,ê#ѼETqP:ƒ_¥oËE;îž{WQ‡.vv'×È uÇ 3;;åb^ïÃioøÈŠ÷^ÇÃþÛ6Ó­äõèuñzözþúýkÀc¯~öA5×Ó:c ËÓmÑ }M|-ûjÒL%ƒÅ³Y9À±ÓœòYYpä¨ó½§nŸôP|éÃöÖ³ãçÄ!ÿû–³8^£Ÿ»Úh‹§žS©‡¥/³ø S²˜z¨›¤3zöüéËÇ^®šT R~›y}÷=ÍkɬŽžW«¿Í¬N¾= ¶Šç¤Ò³»æ]Fh¤”Û¬p1ãÅéÛžo_ãRÖ2_Sâè›ÚcëSGþr@à[÷Ø_"m¥1;n2.f]"%>ýº Mx‚zTNìåpÁ×…¯¸n¼×uSÑ_·°óëÙ©wq]cϯ óq#ίs°ùuŽ2¿®æ×9¶üº„•7zÑ  ë[~]‚ʯk<Ðu %¿E‘'m.3à°’è_ÝnûáÔöŸÑMcó½ß‚>ˆQ¯‚g€„ZÙ2®ŠC@Cˆ•SerûÁçú‹Oõcœé/:Ñ8O§@cv) tSã{›lIž¯PTÚCÒ«îj´ƒž…`®Ý041,Nвr¢r§Ï¬|3FA4ïü+@夗åÔ BLÞ‘€‹¯r,¥G®ö Ÿß{ʼnÌ&}ozÛ'áÁÐ÷7ò…»Šça¼®ýØ“È&QÓÍ/d5<åPÇíJ‹V^¯—ØèeYü5Ahbõߺ•~€h lŒšT½ãŸWC4¼2¥¹ñqKÞi™×Uåg o¾ÆWò%Œâ*—zË…`Y‡TÎ0A.qº³©|áÎ[Üô@ýTj¿zåQ=”© yjQh£vjŸ&èhÇfØnº6ÅË-ihªâ¨z4†ƒ½2^¡Õ¾]]®­øU&¹ÉLã‘Cd§’s|ø¦¶#÷B·n‰»f¹Î|6íxLå²”´Ä‡¨åÒÍ·Ý| ¬¢(p¶_P´Œ§<¨êÁÆQ00Þk†»ÄŽ=‰L®5$€@µÚöÝEƒZ", {‹ä¼.i­î7ÂV4_A=x¢YžO¦eUåRC§w·3°„µj‹ŸÐŽ·œ¾Õ‹&ÛK–,>ð/à®.àµIØMŽ´Û²Åbeޏ}«C o 0ë—´}zp©@ýåúVP} )?Ì6êô6 =‡ã]N= úKð‹ßºQ’Ÿ` ùGªüBŒp»‚WÕdåËu¨ì=,K‰¸$¹ClétÚ(äaâ»Ñ˜Ë–¥yÝþã°‹¾\ö`þáfâÒÞâ;44ºPÖÛfZ›èÒûæ`Îëm:>å·¤wý5©ù†êºì,â…ôl})šï²8¡‰ÇDn±Á¤…HXX0Ñàdb…©íÑ©GÈ¡­> 4ÁÖç*bm™% ¤-€½Ü_À¿ØpðÓˆÙ¨:H®JÜOA,µúÝrÁÞ1ÊÝ;œ¢aÄîGm£'Ö<0Dk!­Ü³)`·X>•¯lß Ú´êÖw€YE;¾ö#]%¢ÊY×ü'ÍôžÜÃV7Ö€näñ=îIý[N}ïu¡ä.ÈÄÒˆ6q‚íˆáŽ_Gá `éÓ5…,Üå“å¦VkÁ7ó1&Aÿ)yüo'/ß|}|òäûçiüõÅ÷±—ÓÏ_Ýÿ/¨ÿ2,ÿ€ú/ûwîÞÝ“ú/Ôrÿ×ùtÿà÷ú/¿ÁŒ -°º,å—Ì¿·€áß[ Àðï-`:ËÆíXU"éqZß,Håík¤ß”j1˜& ¬õýïÇ.ŸzrŠ¢ÑRñª½-r«h¶ßª\ ­¿¹SCä»Á½ßêÓ앨€0¯dîJyx’Wsþö!NÏÙ)H9õ\kR=â̾2ö‹Ë‚a.¿Ê¤¢©>Üùn‘Þ¢tÓL:É–Ér\žI=k-ãŸ{‹öE›6Ö~óô¬ SÈÚVj¥Ê—'²SßÑñØ|.ÎhÑ¿H™m‘;,;'ÚøÕ·‡9쥧‹¹%œqx å…økEj©çVSÇôõ΃ˆU©4hüâÛh! Aýß‚ðGßÑ7à\Rçå7éÛŒëàÖ¹¸àE_0(ø‰‹±DNzÙ= ˜»»æ~|' ³S[Ͷ*”ª¿N @´+Èié7¤ª–N眽éY´7º³¡sFå*‘VxQO—V_·Ùò·’CZrYÎOÌEðlgöYV¤tÀ°ÃÇþ–,ÛÝÒÚ•¥Ý†˜) º](Í=´Zó®ô!Öh™ŸKhMd¹ÍHáþM—ßí‡shG=õâ/Þg—ðÏ£®1Ùðñ¸k¾2\v9¨Ó é¡O‹yöpÊö´Z•3õ"œ§%­ ‹Æ°´`›UH$ÚR¤_«æâNƒÑ¾æßpO]¹äôE)àÄAYs?†°¨š¸šb`¦Ém³´5ɶºz 'ÉÙ é»\aä)ðRÅ€G§¦Ç+›"—Õ»D bœ#¸#¶ü¸8}2¿@!O žºÃ ûÝä[ñôD*+\¸Û²p¥îd¸0™»…é¾;i‘K{_ºÐåëBN"ïÀ·­Q#“¬Û;™¼Ï¾LÁ¥“Ù¸aÛfÅÙÆ—-÷œë&Y¯®gkâë.Á(ñjxt¨\<˜Œ![‘{@ù„DegélÈÓág’;YÆ!àb§!'@¥KàJ‘Êm€GÐÑ5tQ9q;ìûƒršË¡s‚lq66d„»8/CPp€àqauŽmêÉ‘¢6+aÿËžv犖¥¼vÙVøSªãÚ&gR® óRª’W»»0K¤D2¿rÅ×yMZ«¾c^8‚6ym=öÑÓðl Ö ªoË¢x)k»kð^9üÎEq¥Ä,Wrfñ%X+棕H¹t. Lke[nUœ-Rà¸pI1xH*/†…”„æ‚Ä(˜‰7S© >39ö¨E îzcöÓtÍUæë–ÚÅ™,«´4h@Ï=¦Žœ^—+!iÒhj_3sPD„ˆ}6y9kE{þq†V¹†îÌõJ—°Èf\GTð§æWãíÄlpÚoÚ…Œg¥ù„ƒÝ´-Sp"SZ$—Ž ÙÔï”!ö¸¶«óÔÑT‹BDÄ)”eKÐÔÀ°ìnI+4­k„y’¥…N€Á8&âph?˜”lKá™s³ä @&Èõ"Äiÿœƒïà"Û,n Ž$€¯.‰nMØ Un÷CȪ\@ƒVKKiLÅ+@ëÆ§Zd–©:³ œSıYîÙ0§šìrÛ\…ÝCÚ’œÍF‰”c†ýG®N6)g—³ˆßÇD^AðCòJ/}ò% é˳ð‹/j÷ƒCì¯Î_I¡·¨Áô•é7ñmöÊê—á[õÊtøöò›Ý:ºx¥ÊR“ZÂ.$±}T󧻪úl’¸]¡.‘~“W:·´ÈPHA¡Zμä«K…Ÿ"Cá1D{L)‹â` °Bž”±4¤¥²£.ø6ds_’;û‰^áãÁºª*R‘qW¡´-½»t.]ƒìôÈhûMWcÀä¢D}¸¡DÿnQž„Tc“]9—} }¨¹HN!hqHÖ<ˆ4Áß›7(8T³lm3ap¦õç§ü [užl¿î¶¶{'ýäÌäH¼Åöö¦ßqÓa¹8õM·Ú›£)€šK˱ô?Î pV­ÍSm>æ{±¶ùž6·jp"”7›¾ùé~ Lö]Þú–"†P6˜iK+½jµ9êt[åI§.«¤Ëíçßí4€Ùöý4œ«ƒßfYèJ/c7µÌ®…'”tUœ.ôÍO{{¾úPã­â°¿¨P 3‡æj, MEULbâl¨]êfçt!h$ëäý±bÁÓ§ôôiS ;¾º6ÙêrrZš»>_S¾p-WÙƒDÇ”×i¢~„áu‚ŸrðšÚ_ÞCµjZ¯ù4#Bš—³P‹g&a¤µ•c…a€RDºZàVE¾æQ7ZŒ¬¯¯——S)×ë1\€ Ò1*ÿõi nïRѼn½æ•â*ÑÍ öß‚oé>ÑðBSz7Pº”$u·JÃwâ$Ämœ“cù[ÈuWÙìrhâ{[‰^]80£M½¦È/^œF­_Ÿ üšÎ:˜›/Dÿq¦Å@WšÔwÍIiÜãxé¼ÎòrØàW‰ÔŽS1‚H†6âã£Þkrmý®ƒ¦qmõÉ(ƒ,ªÒ.ü’ˆM|(z(Ž¢oLïZ±ÁÅ˜mµ’T‰–¼º†M“/Ž‚RºKɃÁ®=—Y‰z±r¦¸úØ–§|AP‡zÑ«€ñ¸NËS• g™Žæšfb,ÌŸ³¾ !*‹ÁQì B³š;ù(ª‡Dã.żOt¯³¯ŸVp•êi+¶e˜nƒÅ^ÖPάi^Ý‹SöÕCF&Á+hxò¬gî ôºó,ð^,eŒûÅw•Mɬ‰3¶ q:.ok7ÜÜœêsà¶< õl~î®!îèÌç4­_¼!¦Òó“5ÁBį ²cÉE‚yÒn šz©¾HYŠªÛ0kµG · E6ÝR ~®3ï:—(‡T´¦~ º-Íœuɨoäpu ø<pò¬í¸«d"w;e‚0=°êÒuÓ‡bE§Á Iáò4/”9/‹¾Ç„cÅËS¿­âZÀkšŽuŠXãX« P^@ZF1m HB)ˆl\òà™ä³ôZ!ÝQ9ÚfۮשTøfU &Ö>§¶ãZ'šhÙÙ)¬¾(vIQ~MÒcxýÝ8ö­!(’`'¬‚]³®²¯Qa>sRj‘ï5/)®çÍ0x'¶NH X«gáG%L×jœ¿v§‰WˈӃ·Gþ¶Ü–“ ¿}¶´lôþÒs•Ä Îñ`t£ìÕA’¼€Ñ¹ÊêìŽØöR‰-:C:7839F.LR'â)c§î2"ñ už=¦ »îî×ÃdŒØh ‡ „LÒáf]„b¡» ·À,•òî7 ]k ø rxpE¾{ðŒ5º d]ì±úæ£èVåœ ØxT3,:]Ä üæ$×k»œ9RÔ®n2K¹Ê »ÿ™ÍJëι0{ÞLÕ*âH'8 ;^×ï<Ÿd°‹¶ySÞÊ“·‘cÙñœí\U p¼»gVãMŠ^Tf½MXr·Ûd ¬Ç9µLòáP|CÈ^6äΤÍR½ºDÿªÖ|œ›MŒ{ú6+'PGk\ÿAŸ-•Ekˆ&Þ5A`õŽŒ¢ð,‚^ƒ$ŽÍ®Ÿ• œ±.¬mªÊâ8 äɨ£DïŽó¬…B͹™5¥ãmæVß²J<îC(˜GÒ‚:¯i™Åý èð_«Ð ÄY¥àêbT¸Sjƒ!¶fw—}¦œuGÙEVÍëÂØ®—˜Ô•Qìdm°œsdAßvU ~Æ–¿( 6W÷+.›¾(ÚJP«Lt˜qE^Åz'Ï’mÄUB‘kYLyˆ[—%›q6šk3šTO]x!ës —9³¦vVw÷nŸ\;é''If k´i®±pŠp_ZAý‚Žzס09òçà,Ð¥Ì%."V{TùOÁþô pè¹e÷œZ¥çV/ƒ§J0CÏÉàš›œöÞ9™K ;Ñ’ÿÎÜÅ>Búh[”<% ÌàDÌ^C.Ì38bVgGÔf›t»Äo2Üïyåȹc;+¢–¼4ðÅS,Zz‹%Õú>óNœX3ÇÙ¦ãªlE}’M¾r(LYÚ ˜$RIéºb½”·ëÉ>}Ö¤‡³Lâ!×ü•¶ÒŽÈ—?10¶(OçÅæðaÞÜ÷Õ¹ÌæÖ8MÕ µL$°È3¯ûÒ ë%ïaÇOD—0éG™§²(ðDñÕ,¾Îøª Yî|ØÝ›ñŠÅ€çÍ5§C5ЕC°kÎršBpÝ»:Ð1KÌX´ªek2³¸¾·U{“s¸Ú 3°Êg ÝŽm0Ë$(|ÖÂøØÃE1ÏÇm¦U5I)âé7ºxÉ\ ¦§Yë«!µdÖõ| åýr2ûEäö•È…9“é!¡f¼hÕ>k¦­ƒ8VõùÏŽ7¼Mä‹7–” ±Eõ`äN¥ [8ìÐÊá-Ç1„Yø¢•+hJ¢‰É~š²öÍÇÍ5! åYä¥Îˆ)™Vª;’äÄ”Öퟦ¸ÑÉ^í6îûm|YßF¿mnš·ñóè6ÊøhM§Ã:WOŸ1Ï£Š¦@]¢o¬ÇzµÚ7¬\w.VØÄláª?;ð˾øEËþì‹–uû:™_>›ƒÔDì"ûWõD+Hÿ b•þA´ªr‰¥J¿!B•þ‘èTú ‘©ô£Ré_ŽDí™+}ÐTŸE£Pë|¦ª ö Å€ •O+S«ë¹™`´Œ“ p‘¹I‹3™Eña.8IƒÐ1¡¢\F0ŶtÕèÁ|Sk=áæ QÛ1:Éé›K~T·Õ ˜)(‚ÐǸ7à„v/.; ]uS[‚´úÝ`çÚ&²×[Ù¶­èe•†C¢é„ZÓB«Uï”ït– >Ð3Ð]šë6¹ x)æŒÂîs‘ëÆšåÃÐýÙ]Æ’)[¸M_tÓ˜–‹O×)DNÞ>GN\Ëý&þ Þäšy§Q`ìɳ*ŒÐuÎMH®;!„Þvê°*~47*+ÁØ‚È÷…TUÉ6 rs¿[wrIÍ_}Ïû¥5â11ËEÜ×ÑÍà Ÿ‚´JkK—äÆFdí¦(ÓS çFlï m'iüv’ø¢À§ÚcWŽa‹É6‡ ¹¸è±[ï KAc‰°ò]J@RÕÕˆœÂ)›Jª÷ÌÒ 3îˆØ´l=F$—¨ÏB Ë’/º°º%_ŒÛ´ÏZ6¯ƒ©›ÛF³4¶‰øÂc q`:b8aV³<Òn-b‰”s@)g r€¢rGZ¹ü-7Ês\’ƒ4ŠN½)íúsZµU5ÎFŒØ5F̧våËÝl6H£V¦…nÎ˲rü7gÛoaÆ.‚¸Ë¬”‹Bid`Sl ùœš¸fÞcÿFø”T.fæuÔ£KÇIjq±õn”j£­ÇÅQ€¾3¨çJÑ*!vméXfg†áئÊ6BN—×ìnRP…‹Ç76ιöÛ§ÙÂ_ÓŽmhŠÎ䞦Áé4ÇE(ÓÍtÉ}œÓI4†ìp;ÃÝ2”cƒV]7Ÿ=DàM¾„ðy®‰y5å(ïc»¯© ¨C\©ûª™®Ÿšºe„Nê»69¸ŠÄ2-^‡šëî]í¹Œ)Šo‚Ùƒï>àSx‘óxÔª)':–¦csk¸ˆ5-‚}š;i™¶ÙU’EÕ™ùhÞ—n|²­RT¼½d,L騮.r¹bt7Ü0ûKÐmPx‰¢(×ò%ÕÑ­KW-OŸ¯¦žj5g†ÇIÀòÐ-.I{|baHÄæ’Üõ$›Ê«943-¡*Ü_‘‰¹lL¨v\㯾VÓ@ËíÏÙY3þH \³ÈË[W³œ¤’„ Ë‹BÍýXñ,3cÁ{õ¬z®Â/©åØRÁ~-ìiÉhÇÎ{êºÿN¤šç3˜FZ M"HŠä¸jÑž²#Ç¥sï >["Ò(»GI5wØ9¹F×ô;œ(’óT¹ó§Úê4ðå]vcµPjþ¢¼ÚÐÝ]fÔ¦©ò¡ŒÍåzUŸ5N² Éò^j6 ­&WÅ’bÂÈëè!ÈÅ`¡_ô>JÄCèT3*V¾b‰ÓéyÙ¦_yr„Šî† w½Þ|w© ¨K¸Áy±P ž—pˆnrÜìæÃø„Æ' =w8¹-î»è)@[-wÒ¡1Ÿ[+IþR/ÆåzÕ jž[a22e‰]Ì%$¦E¿ÀØ4ërÇ}Wû-‘NËøêªU“ï$|©#¦^Ö—­X‡çYÃÿrÎ8ùés†dX`¢´Ž±F…HÝH+ÕÖaùd$e«Õ‘Šå¾JùÅ@y–ÎCÔš 3샃«.š½h¤ásÎfÁ¥8åZ™ORyyY·0Çîò¦¡YÛ¼JBFs`!i ÁüšùyA®ÔŒ+¢2®[Ò]ž…ØÒj¶a¯3T¾cžjÎ|Ì-käxæÆk hÛÊC&ë< (9'è’-™›+ã@¼"ƒ°öˆ/;Ϲ0s·xl¨+ŠÑY¥üÛ…àãÓîã¢)JÚ¸–Ü%M›ô¨y*DQRÅÊ3*,ª6]a›’ÍW½4Yá_s7ZéTÙ²ˆò2 í»}@ú-Ä¸ß AR:\RÓQØŽ0yW‹Ûb>ç.*ÉM¤Šó= Ùó½8°×z¡ë_]âì+6Á¯X3L4N~•ÓM/vkJ~ñaÙKÎËñ¡§Æé(Z w‰Ï§/½/™üÊ8EѵۤãX8Ö„Ö3¯%ÛG]ËÿÙœV$ä\Ködî­aÉV³žYÒ-Ýhì&ÃN€ øZ#³»ùcúì­Aÿyy&©ž]ê ÀŸ5ÈÕÈõð8U »µ„3¡jKÆw)¡C—³×ºœE,Á¤ƒ·éŒ/ì”Ä)^ÖGM©R • Í”`§%ªÝ)‚‹Â7›T$ž,zžÖ(‰ËQ0¦Gþä”è{+"«|¡xqYIR7)Óæ˜•& †íxþŒÐ ç‹ÍGq¿úD Ö²ï»ÉøhÜ0ÌÂÚ³`ýò|!ú m¤óW=÷û<ƒÒLR±a jÙ“+‡Z„öw=Ø6°Ä»¼¦òƧäfè æÛS9úÒ’K{"ý{ˆnP¥ùúØõS¥8ñçSÉ´eH]Ì\ZLÑ š¦Ì›£˜cž‡¶cׂ7Åö»K }q”üÑû—u]æÆ vÀã+¦‰Ç-=TÒb€)$ˆP9{6‰Ç¯Ô+.˜Ûø‡APSÃ Ž”ËRíØB}¤qú“ÚY† q”{¯G¯ ;+$z†Ç\0šƒ¢‡Ñµxi£Ï’R>R®éðÆ3îõ{Çájb`1–>PZ‘¼"ÀQšæé7GCM1°Æ·¨Ý—¨ãc?—ù­÷rµ8""·÷k¬æܦ4DÓŠpFdhDnšefºvºO˺ÐP|F ñ2Dd‘ÁÎÂÖ,8ºˆ°%LÕÂKšœ<ÓÜ=ê3¥»•ívuLÞ{çÝ2Z²Ú9ûÿ0\ÃÓ Â^}v^>•Ü»¯š¯k¥™3d6.r]Ü—-ƒ´ÉsÉgʸæä™j $5|Kfb+ÕÙ¥Xò¥Q˜–¸±ò´eõŒhQÊäÞWKc9"ŸªNá3_­ €`pI€,™¨%œ›e¹W€£¦VQ›h AAèLU(M©ÓÊ*×ü@PD‡µm]'o5w٠ƬƒÓYù–,sÂ!K琢t¡¦‚ÔE›¡ÄÍOì]\-NwùÑ­îzGv3Nw šŸ gº÷Ö">糕ù±COj™ŒeUåVÁ²’_˜“Ò£}ÑyûÜllgÍV›b+em1šm/^ á”Q]’1»ŠdŽ“å=b–dø‹Ó`³Vzc0 œêsö^É-ôÕˆ·ïI²} vdŸuJméØE=;Xo5üy@`½0—á@¬?kJóøh5Ü'°~šj¯R­}$;HO^Ï\9£ŽO±‚*аíÄye¥^Ž){ëYfp”Ûd Ê# ¶zªV~…Z^¥]­î–¢qDŽ ¬UÕÝNýFW³šp”²7_‡³Ðç®#‰ÔœµW¡ÕÛê ÕíH~_ÔŽp§+0='*t»°)y°ö=6†®V*†+‹^Þ×+X-&N€ã:­»å÷×ÙoüÔfŽvÛmf;Û²±áE»ÒKo‡i\#C]¯f/CEõ~"FP,?Õ–§‹2¨TªL°1iÀÛ2æ „ŽG6WX¹|#ÁIκ.b—R^ë1W€@).Öò¸1“ð¢ËUe’I€/â‡Yæª]D_]íN í¬WCeq5!Qƒðt òÅ%â4Kë'Ð)8ÐæÕŒË;™ÄÔ¶BA7 ÕnNÛXúF<Ãg|‡8ý.S«³tº MÄõû…Nî’¯Þ6§*Šús>Z.!o°묨 måb c«lz·K-»âõO¨‘¦âJw·Ñ~½{{Éà.%\?š›^²¼6Bý &ù8øY¹}__,….)‡L §E¿I:)k™7k; >ÁÅ„{‚ iÎCà–€w€ƒ·ÝÚòê)(ê¦t~CˆJÅÍj†¸¯VçN¯Ô¬¹}ŒêïÜÔVØ!c;‹—@#¹ÞW¸ŠÊ ° ëb,‚.”ô]xmäÇ„l63?17¢g—9d©ýµ¡Ç½Ð)Zñ%S×*1Í‘èä"âêt\!Q ºLŽ*ö©I‘À¼¾Öq¯+Ç)ë‚[§«KybëxYÖz‰7lš,ýi¥k]rFáä®i2°µ¥=âÈ-Åãœo°jæl„n8ö¸Y5a–kR…݃6cG¹”6¤UP¦5¬‰ÃÎbÍ*ŽzqÀxÕ¨S&n\„¹Ù£Â9­Yøh€y(nåuG¼ýGº7œMPžQgµÁlŸ6's»6þB6(˜•Hc$ªo3ô  |~8æJ›™Ôãâ7ž~/63„*º€Ëp¢VᔎŸÚÕh†`õëðWSó¸w×€ào ~A^âvÁ,>ÀÖè9o“ÿðöu^ø€Oª,Hdh0§<Öœu‚F¥*8±° ºX‘%Ÿ|•<þ·“—o^|ÿèÑã/Dÿð šÇùiÿü¨Û¯õ÷{^¯e¹VÌO5PœÊ66lLAfðõñÉ“ïŸ?öF)õ €Ô;Ðú$ì’¡QÀÐh&_³1øÔAÝSq§ûä”–.ÒŠõ‰0ûôÅ犤æEà¤ïB°§<7;äšµÊ"¾ãrÀá(œ›F<Úµ*ÌÄi_øñ½-‘ÿD€¹Ô¹ÔÉãæLp-™õÊ’•­%‡”½ÃG³œ.ëÀâD:NVâü=ê¿Ô|Äú/‹t’°j°ÉDêž¡ÕùD3¤Ãˆž©Ã‡¶ÍÎlæA[d.Ðh2ïZ-6i+ÇäOÙ™Ÿ‚§VëØ3¼(Ñ­GäÉTè"õ¹UÒ ¤×¿ üO³r:v^=ß\¡ðÅ…W{Ô¡i;é@!¦p¥æ—¾f¿8’^Ê ë!9‚4¡c>…=±ßüáQô„­q$OÁ Þ ñÂârf¨+æ0A•µ›ÈÊ3-|8Fõµ¶oÄž«Ù`¡÷–ûJQ5¡9Hy@–føEº*~UÚ¦¨ >‹æ7äü´"ù ƒÕ¢ÿG°päóEæ×¶»øñ˜³¥‘ÝÃ`(€>CÖ>'‡Éí/6;D×FsÙ!úÝŒÓ/Ë5°Ã¬b'(Gà³~ˆš_­fxˆ®Mý0k‡ä.lf¨ ]u˜4û0›rëaºá¡®Üåe‡Ê˜ýö[Þ?úÛäø¢v-2XM²öõñF‡¶[qžQ«Î4·ý’bÙQ»•‡´[uYÃvËÏ8i9ð #¿(ODBå£rõâ±$¼æXÂÚDÃÔ*íGå>'´&‹ÑbÌUåËâG%]Þ‘ Ö»]©»Ë¥¾³‰ÞœU´w˜ÏÁ³…tèšq ¼–÷¹T¥d#•ÕEö.»^ê*­r1Í~öÓlÀ…ÄØÞâÒ£K¸“X¹Mh~§„Øîu”üððÖi^Ü 0ÍVГø è¯y ÍåÐ÷9I§ÉÎNò_×~¦æÿñÍÏWêrYÿñ·D{LÚœÍ,þ[.Z 1öÝ)B줰î\êm›üÇ7Ü€Æ Pg—Y-Ñ`>ïÊsþø7f#+$)Ö xÕDŽ k{…ôY†] Z­j/-¿ßûøÕ…VsÄn§Ýön+ÔŽû·Þ˜ èúU ûš?šï}ØÉ·ã†Ðúî†pÐ~q7‡Öw7„ŠÖw7Žö9o#Iòá Òþîf³p~lƒšlÐ¥`­:ä4HÝ?š7\N#BPXÁ¶ÂÀ‡sü1 XvKdêñ×÷ü×à /=ú¤yøŽM]*Z¡9Ñ'‰h¼Ö8~×I°% <È–×rcÆ0[Io–¬r­ª¶w›X­Zsì´aÕr‹/]VéûV=×DzëØÀÿ-²þJö¯†µ’ƒ+Û¥“Û«qÑM1ÐÝ+àO7Å6Ÿ] Ç|~ÌòÅج÷÷>_|1Ý?ˆ˜ 5<Êèˆ7â;›Gy;ÙŒëlÜó;ÉFúÈæñÝM6Ô@¹#‹`d-¯¹äv~–\XrûàPSôdõMD‹+ÞD¼²âøøñ&7 7½‰GÁ[Ï69Ò£«ÜÇ£oãÑZÚ~´N±¼åÞZu¼Koa|î¿øHëÇ5ß@5µÿà#m£¶GÝѨ€Íц7ô2xeíMM–ÞÔu÷ôÊ·tåÝð†n|?%÷Æÿù{9ÜZuš¿Å®¸”W»’W>ÃÿKñÄÛ­?»~ðÂAæýõǾs»Ÿ<Þü?©I4aOwú8›w1h{·¿êÃ^?í'Ç›_ÇOÖKÄaçŸõ“¯6d\Ã×>ïÃùjóögÓýÛÃó­MN8^ÎwÜÁÕÎ>~÷£Büö¦P¿u%‰_]Ç'bz˜€—ÚÆ|ðÄ}¬A·v6ý»õÏâ±ÓbÓY¡š]¥Ž´ÉßÇxçÕZóíï¬4-µ½³ ×öÚ:ãBÛ;ëþ~ø[÷k9.µŒu…KQGÐwf[W¹_›\«¶ÝX®˜h4]iGÝôºµÇ —Š+œö/hºô*µè×ﶦ­ü`{Ó%÷«­i+¿¸üæ6|Å“«Ü¼>|_W:llº’[ÙU._«Q‘n]öûµûý.ý’»ôì‚4X½¿–YòlAS$´Y?p”ü5-2bJ³–GGË>''ðZ¿1OF¹W´Ñ E!‰««@Ö8Jž""B’·¤g´ƒ×®]kS“oœpܤF'_§ð™WZùæKÉÉos2„„Žãö¡ÏëíEÑF’‹ˆƒYßJ<§_‚$³å4HþÞ»­Õû¼ÑF·.å&GíZ7ü7Øú wÜov¾}Ç]›•;_Ãü{ï²»û¿ýž¯Üéüþæ[ÿ(,²~³ÿi0ʯ¹ÿÙG9€ßf£7ÚÞßj+4ð$a®ê¼”ø©™Ô˜ä<eÐ)‘ö¯fD$Zㆋ¡B”âlpžf\©ÔOóäÆ{d@îôst(É6*dF$þªÊ?4ì{g[Ï+4x­Ÿ—LȽ°lbÁ¼jz{gƒðÜÂɵð1çE¾ï%ߤH;Þøùfr\¤Ä¢UyÚúô(ùKŽP¶kѯô½þ&¿$×yÿàâa3ÔCYœJîád’i:ˆñ¼¸Ñ²É1|wóÞͤÆ4‹Z»ªÍ×·~­«×½|>d g™NG´xjÙ:ãD2…Mgù$å’y˜A†ÈƒBZü*Ç8¢¬j5¿ÁÍO‹JÆT‡¡¹MË)ç  –¢úó}‰½¼½÷õŒÃÒqÄ­£Xí»¿°òp¸‹¸ýf§Óy‚äTRC»Ð]Ë1ªÁñ E¶ü2,"²ñ¶DµP¢‹”ŽÐõ n ­”ô¬ `èkä"—r‚ØžÛ¨ ÒO†ùYîBˆQNÇMäЊ4j9QÎ…ÎiC¥l•DŒoé0[ g}×,¨È›W„¥O%Õ’T­™®LÓ5Y9ݹ•®•\=t,êGdõbÕ.u‰{ýlÍX»ÅãmÅÅMQ,>/û¤ïË|˜ 8ÀÜÂÒ%yW\+}[O¨–®•ÓrI¨üQçH 8?Ÿ•‹³sI´vªkI9}b½~,]bø.%¿'ªvc®ç4ÿK,²žo˜ŸUYð*“-b¥úÉþâÇ1n9ÌqúÕ³R‹ð^¤ Ú˜%‡ÃKÚndÑfÑ)[ αä½â$IÈ0À5œ$Ig>WFTRøÚ1N´ð W3ÀãtŒÒ#—Qq Ÿì Aó|Ôéi%!ôVùÝ]šK`üŠ lGì¾Êçb¼ 2j}¾}–üƒf—NS)&%Øa´`<£¤]P ˔ì¬åo6¹?Ðù¡xLΉ–é@ß‚†O!Uä– Ôœ’‹‚&]ÐvìñÅm­3Á™›5)ê„Hù@p–RÙ[Š­ëWoïÅ)Dât~Bõ¤ìƒÔE"FƒÍÆRÅV+é 3Á+àehç´H©Sàb¸Oßk!‘W“(CF4ÝÍsõ¨ÊUH¦¡ó!*¹i!!Ì^PX2Azá(Í JòòÉ:GW9ŒÓ–3Eû¥\FÏ.õ ”"„ÐJ·lÑÙÄŠeqåì'é‡'F28eEp† šE–ÊÂ04ªlȾ»k=·ìâ3Þs,Çï B±0~5/ø,fÙÄ|2,‰T â¼5R±Ë&lI‰¶ODëÇÅ0¯¦„“‘¤ÛëX:li¢RŠÍ­ŽõûJKúÊ ¼œ“ˆXIcXŒ ¸½Ÿ<Ìü\RÍú+ÔüîšïïÇsŠæŸöôЭ8«,¡'&Ôè„sï':Oºaó1òÐ#+ Ód(YH$ÄË'ŠñÌ +é+.¶¢åM£6ü\nsì³”3zÕy?FBEi)õñ¶mÝÞÝ|ŽTào]éKNt.1DI?¼1/wij»(Èæ^¥92QI:.Tkis€¿eIùÙBÊFª³ízAôkH¸é$ãÃøƒ..p#Å è|'=-#0*Õãzr[µêÇXÌ8Œ*‰B¥óÁ¹ðLëßt™æ(j@•¬`6oDC nÉ'Ì "¿WOdW˜ÒÈ#-¯'öZò©<¥±³yfmmú{H âØ¡šIaZâÐӣߘèav}™Þ¦gÀL>¦uì M1ò:a$‡^.iEt{H#V^ÀIðý²±™ÖÍeŒ‹4©EʺÌ!æ>W’+3W-Îd\0ÖT&_!ß“ró2b#Ò*O@M3Îå:l¼u<¤‰}ÓOÁ2H‚”î"ncQ%ËŸèjîßõÉðÒ ŒÐœŽíû"ç[8 >%xz8+K0(taA2¶~ò¤\ öÐ7O“OoïßÞÛ½óù_¸ß¿8Vá ð#žwb3ÝòµFd¾âz[Z/®pUV}2ÅöœÄÓgö5Ìãs s*+3Áb«”&iSé6ÂÂ8åz/.{&àÒ÷´½Œ'µæ×ß ¡¥ó`·Ïçóé½[·...úáQÝú:¼[ÔË­zÒ2laCªÌHsÀàã$O= …o”èŽg ­‘\ÊÚFT,™±GS~ÏÊn®rɵŒ Í?ŸÿíÉþݽ[(õZ~Cä8áùoooïÓ½½?ìííßÙ¿ƒ÷>ûTþÅßÝÛŸüaïSjt›þðy¦ôÙ?ìýá7ø[IÒ +ÛUóʸ-_$ýܾ«‹:øÃÿ’¿O’Vó~‡~O" þ݈6sÁïÊé%óØ|1 »Èïu¨í[Çít>ÁŸü—d-)‘Ç ,y@o*-`,N Ë¿–êÒ7ª’¼OIƘw}Ú;d”„ž’‘¸O’± QWwŒÉi ¹C‘䆥²Ö‚ˆ…@+–Aûê„_’ê¢I¿ä¯š=HVÊHUÒTP+aæù¨Év÷ï:Óa)¢õp…Ò¾fÞÇJTïwVòôUßgÌá'ÀÜšM¶xÞ‡[[É¿ìpÏÛÇc©Ö˜³`5Ë+ÊŒ¾”pdÍàt†ÊÀþ ´fÔ {ÔBCaüÒá{K‘*Ü* ‘ÌD°ºr(gUª’] NøœÁtˆ]²,k4“忘¶öã[÷¨,˜É6Þ]»¯p”ب`”ñØ€Ù~ô †wƒ¾ë¢Äîvüí‹“ä‘3c£·¸é–¿¥”9òË­>õcÉXCu0¿*ù" ŒÆ¥hM¥z IÔ$9|â@™˜âΤ…\‰¤¾ñ7 Ðåóí®KˆŽ£XÌKê ©)iÁ_W|§' ¼HK´÷šäsÂßè}fÏS+ Š{`E¬+Å v•çe)zäù,%ž+…ZET±Ùh” `±ž€ ~¥ånÑ’¾zúí˯Ÿ?~,KÖîÉ6€ëE9†•ôSÊ‹gÇÏéš“G]º8ÑÄ>Ù}šìVÉî¿Ñ§¯¬×NÇ7à€¯+ߌ@Á-.öËò@þ¹MÿÈÓ~ÊÍ7«:0T ôöV?¸OÔ‡‡zÝãUE[A>ß„ ¨dôJ9 M¼¾ ž®¼¹²M²}•~? ï»e§ãŸuŸÝ?ÿfÅ®>ÿF¶”7”·“ˆ"\‹¶ù­³ÛìÊ[§Ÿ¡x£Ëüë .PK«ÅaUœôfÕQæ·„ÚC`&ÔÐá!ƒ9< ŠJ-ª]…‘1mQôòSZC?ÜïÇ«^®A:xÌC˜óÏ‹9I¥žPcË,1/ÂÒ§$–w ±bÝ4‘Óiÿò”m‡U6§OÙl6©Îèµ§ÿš®ð_žv:ýÁ¿<½×ùÿáþ˃NMß³mĽuú‹¿hܲӱñîéÈ„LõùÜ?ïtÜdîÙ¼¨}ò Ý«ŽMúž=ÝñBî1¿³²·V¼ä×íõ¥ôºoÒ6 †Þ!ÜÀ™ßM·ó‡ßÿèOå?¿¯¿Â«å¿ÛwîÞÞWùïàöÁÁnwûàîïòßoðwk‰w÷­ð®yñ[­âÿÞ"þñï-â~_âUN/°yšþ§ã „Ï:Ÿ˜vjËßþ-vló^‰-ç"»Á¬¸Ò'gµê¡‡{íï–Š»Hzn™å]¹ì-C0[<? Ã7[ÚEüÊGÖ??ê7RÖ¹>Ð(/©Mü“” ~ðÌjÍPä¿u>Y4Ròí÷Ožt> 5×d{›½ vºÉ^£ŽÐÌqvÖœíöt>#¢”܈záí¢P+Ður1§goæ÷ýs­aÏe8ÿ«“HY{i¼38ŸU÷ý?m˜åÁ *Ž©Ê,?#éeûÛ§/=KÍLÁ×{7ºýf0E8·bsÞ÷Úæ‚y¹Âýe!ú¤§Ö^X¬jöÐÚKmE/ÓiY9S&OWÜ9̤ßï/™ Ô°÷5¶$˜MTô]æÆµ ¤°´Õ  †ú•¿Y-aσçPiªTÔV$†Üûõ^žöݼZ²-Ò‹BT‚ªûQ/ß–Ân%o[z¤^~æï÷y„ÅŠÍÌÏ/ò*Û}ú>@åYÆ,¨ 'ØI2a°y´wÙx(Žèö^|q+Ø æ:yZÆßß¼øËÉ×/%ÞL‰¡1>ÕÚ¨Ù!¬‹kå×ZAá̈æâ ®ùüFøÙѺªºóèûç'O¿KỹK3 3èRáœØ°t£UêãøÙÉËã'ÔÇûõ>Òi>OÇùÂu£µFoŠXòª:ÏGtM·/ºÉvBÿÝ=’]¾žìwƒf:5n¶5#–õÚ!°WÐXæÐÒøŽ5vXçªgî%Æ]œýs-ý·1gç"G·>Ôƒ› µz[¬ÍRàÉ [z²Í¢%? >¤®XžöÐ{Qθ¥Ž/§½d‡ðï})@e·§t»GÀ£=®Cr˜L“›øÉ]¼iò€Ÿ\¿ž\Ë«t\,&Û;Ó.=¹y“þé$V\0nH÷#›qÃÎÏm›eDZf³ ¢Òko—ߨږ´l›-i+¦˜=ÿ48÷{"FÍ`_°Iòc}gŽäwú¼»;í2yB‡ØÅW»û?ÜLJQ²m78ïvm¿öüc¼r˜ÜèßHþû¿ýò§ð˵ð˽]qTC?cÞècŠÂœ6Íýp”O‡e4›ÌÚµÜG‹‹s(5¶ÝÒºüºï«v–bǯ9=Ës.ð"Ÿçi>îqÃ'ò*çt>bÕTUnÒÒö"×kÅ{V·NÒŸò ݘßcYIëê9'ÉQ[fòîb"É»}3Zár®W^‰ö'æG8kÐŽIQqiüÏlVö“7X¦” k臋Ʉ•¡f¬„µVú‹›º*BÒö%«„Š q°ºF`±h¶v3ŒÇÄü¢]ˆV¯y({Éî¾jX´¦¨œ ¬ÒõwÆÚnU›<á;ôÄ¿©UM¹ÂP}¾\½ÙD«v.î+S€hàžp÷ v¯a7w°Ÿøy–À’v€ë¹ï®¢‘6jGÈ™O†5¥kñÄ5±o†¤cŸð(‚N… îãÞ»Ñìšã^½ÆGù'÷Î=mŒ‰¢f8MwgyeÉýpÖòÅÏ¢m¨ÝýûÎñe»m7ˆ&_è/û¾'ü­;’Ô—ì ‘FZúA£ë;«ÿÒ^lvx¢G«1H#?ËÒ¬ëZ냰­<::ôköƒ4öSàÊ?²~£HY²ŸmÛº<À¹ ¨EšòßXq›è•èm”Ï=žë©ÚˆxOùÐé^ñ5XõNb["·¥j gÞþ²83D]ÝÓ㘺ÁñPòàºc#xzIÂ,¾wІ9ŒÉ2C,ƒ*o$“àèÊÙ{ˆŸôŒ…=æAw“ UãZºC[%múØ÷Ñz5ã W¢í6|¹³MÜ`ý1nš«×ýçBÊ£mžuÆÓ,ûºy86ùo#Æ££îæún‘Î2 rì :LÙ&srª‘ÂKX“À‘Eeí~5b!3û¸CdÔ8jÄ@n1β484¦e Ò“ ýW£Ýž_#†77ì^ ¤1%;r Áh$ŽhíuÒIß;òo<º?,¿<¾¾ö` \IWPA¿Žp=×p^ÁÿY!(àAÀM,ð¬J×ñn JÊ7iý=:è6I.HØ•î¯@gõV*¹]Nf÷=™ý˜tÕFÿ0Aa%%‘ï,VŽP*¥ß‘òÿ —Êü Í®L@#Î’Wj²—‹£“|¾È‡Àl H§5Õ ÇñY_ÀÇ!§‡OÏ9°D>³ÏSø_žçÉ â±dpè5 ¶o1²%Í©¨i‰€ù:›4=O+>Ú¶ÍØÙ‘åe•¢ýIÌ-°4€›8{ÃÎ;üðîíhP©Üî1ÏŽyÄž1ÀÊû†<8P¿ôÁ½ bs›LLì`k´¤ÉËñ}æ&õ  0˜ˆü(Æ/EoÌÏ Q¢®s üÎ; Ô%àAØ\¡È¨°4xp¸¡œ}G ðY‰X·û[-¦ž«o¬Ú99µ…FÃãl‡â4þÔ™Væ´“TDÑKb‚#î:Á5{±{ ,G“l²fÂ/Ô¼l–" ¨×¹y+¸¹3ð$qÏ7õ5t_)Ús}¼ëw4’ê0q—ºbp±a#΂¹±î¨åŸ †`èß®7Y¡Ñ®4"ij TQñÁÖLÏ[OðÒ‡*Ú«ÍáLýˆ–ö@æ)‹ZÝÄð‰˜²zW1¤A]ÖsXÇ0ŽÌÍpsót óŠƒ}¥µËV±É”“ÇïÛÆÐP2NÀ}Ý¿ïwÀìhûÞ(ºƒ·éò%7º0î‡Ì<ÂÇLƬTÜ4@`!­Z:5öŠ^ƒK±É„“=õ±É:ºÇäJ/]žJ¤R¼v±iBV]—e‡LO‰pU3¢pÈ¢ŒdÄ„ÜkûáK°êFÛê¹cü|€k=‹ðŸÛlÛ™æÍ›B nÞ$˜‰è¸^Å‹]EÑ#!tÐÌÂA£¸޾ i9FÌNâµnx_ùLTMrÉA0(8«ÒÁRÖ\lСYþ Ûåv²ôÿ>ô~á9õ»tèþ€Wé°Ö‰8~ÄBjà±ßíWܸ6œØ+J?BÝI†Æ9`Ü$ŒŠ‡17—b xèø½û– (6R³‚_Ⱦ5x(<ˆèÒmßö[¶¼¾[NÆñ ¯&ÿ³¤¥ X9¨OÑ´¶d·¾‹ýnøëϸ§Æž,þçà>é5–›û³º ˜IÊ…²Ü…!¥y;„9ì—cÉX~9Jž„hÐÆçXAl,)p$ÛÏB°öýÔ[‚^LB“­¿yÓÂÙ‚t/ùc§Aôü«ƒùÍð*þëÎgó­ŠIÆò½ZO(ZIÅÄbÙ²BÐ HF]ewö ~gía Õ¨ÝöøÃu,áPÈÍÈÞQ›'qsý}·ñBƒ5ÐGŒv÷–¡’µ8äçÎL²f¬\±x‰Ù+ï#Ý}¤¨oÑ·Xbc7´&x @{^ UŒî"cØriý ¡ÒT·Œ2}Žëâ4ø‘õ24£/S”„+¸Æùb‰Ì±„k»ýÄC€#ú¡Ïiüñ¬0ý-Sò•¿v)?¢ÇW0ÿÅÈ£Í+„ñÆ“¦7ˆò,÷k6bÎEÏ^×UTöMåà"»ÉØá•çLO°Á&ª °ýnÙmÝkm÷€Õ`†üæ ÷Ò "Úr§jX¥¯½Ê¹üreíýNLŸ4ªj×iTE·iíeÚá3m¯¿OÎæRöŽäëgJ–ÕØp ÔÚHåž*éÊuÒqoÜ3¾ÇkZY¶t_¹K Í4¢;i}<_ÏxUP7ö˜§É„´úšM9"Ù¡V/Z:tûS—j\WuDÀ3r:ÿn|UðPy×ièµj¯Á˜ó¿4þ÷ü7ÿÝ;Ø»{×ÅÿîÝ=ø=þ÷Ÿ,þ÷üŸ0þ×Eäþ?d5ºa×rAq)’t6K/9Ç^`·’”}ºÜÅ”ÓZ,æìD Vwî[É™WeíýÄuÍéâÔPÈ.lxó4Cf­tÜ÷Æ{uSŒHË9Éx ©¯¾Og9B8½¯5²|øOZEÝ 3©ê0Œ”ýÄAá¶;>wT|LtDA7rLu“  ‰‡„B4;è$Ì—Q: Á»A²;…¨›ðH4/²ìo˜›³¶ÊÑSÖܺiø@VÓlòAj¡uá†}dµ‰fƒ¹œÅç¤á±Ev–"È7eâàqä!%⌴`ÜÍïé2þïæÿà|`tͳê7¦ÿÈúÁôÿîµ<ø”Û}>àwúÿ«ÿ%Kò0ÒïI–ç1Y’ÿ1Y’ÿ1Y’ÿ1Yšÿñ1|Ñh§g@Mãò‘†Jó±VšÍP+¤HîÍØïtdf{{®¬Krp×'jwIf%Œ^Û¸×öÃ×4Õ«ïk’u†qMNDì5i'E˜6å„ã:[Q—‰0=%q ¨¼™$(÷´£µå£KÉŒõ€i ¨µ8dôƒÚgQ¢NfÔ I«(¿»Í#Ç$rsoôy:¤0«Dĉy©ù,•Ü·J„‚”Ä’gò}:·.W0g¶@?–b ä¥ü{D|Z²ƒøÊ.üº$¥Šö½¥­[Œw‰íÉ Ù˜æÒîk úÀ²ûr!4ÌRË3~̉â¶ôï÷âÍ%îAcleñî?;~þðéWÿNü>Ÿ•’Q;vÈ·üÆRêÛî(E¦m…ó”0š_T ¤³3Nm-<×ÔhìЯ½à8¯\âð‹š?…‚ F%y ¯¶¶p0¸Œ/€”¨R¥F+dä\x„èíìYÆŠ9+)h‘zpâ<ìsZ2Áõyº°üËž»\Þ\õX¢Ë¹Ø Š3pê7«·¿Z¢éÜzlÕ8›Í%í¼£4¾ÁÏ.lyœØ_Ê $xï ¬iж|Àå£rR œNøxx-j]†êR„V ñýôŒÓ:ZÍŸ‘Ÿæ‰;8̑‡‚\Cg'Øõµž¤T´LSŒVrÒ ûZ…/kp]üé#ëòÅÚô¹®'ðEdSd§»PEˆ+CÖÜ*举P$§Ÿø< …ðü-ãÆ€ñž+áAìfØQ<ÍÐÏI/iVÄ`SÛ AMЉrÁIÛÄeÅøñ½-‡¥,M»Ž¦_0yp½e§ .ÇÑ“¢ŠÌ¹b} )ÏØ„m€‡MáªÃ0 ºg®Œ†ð_Xq¹™ïÓAZ81ΡÞÓqZ¼ÕX××LðˆûHG¨^ñ RŽR€ü¤HQå †îèípG?_¹£²£œs|hå0û’ÖµêOòjÐÓdþ²³˜‚›&*’ 3ú½­{»žÜ"¾”-³|8‚à]±"Aò,UñTÕsiPd=+ÚsŒQʳlü6ûr°»ÿY~6í_LÓÑi?ѺÆÉö#»ä_ÓÙ8ùj1¤Ìâb:QWŒ#@±$?2ˆ·N&"9 ‘¿Œ ÍÁ¹– šZŽ fòŸ€¦ÇnnåGàXËâåÙš<{NŸï~ÿΞcw@إħ]AÏ!qÅ!b’–çà°M•*½/ïJ‚‰_.Ë”Vu«‹@ZxD!õŒ¤„aŒøÒñY9£û0éùÔ„[®„Ʋ¸g)ƒãE>ÈÏÊ G\¢Îã î²ñ—)±"e¶8ëDS¾â“]T #4½l&ˆQ}l†xãÒBbâúo~R ¥Š cõ]½Àó˜:ù\ùü-’›¢tÓœ~÷ hõ˜ w@12sâ¦óÅ¥«Ï f­ø#š`uYÌÓŸÉWH¿Á•0CGtøËl0‹Ý6Gݼ >ô>«ãUT—Žvîa/y&Hã;_ÕL$’*ÊŠˆ× ðbÏ•ûtLž!ÞB\CQÞ*Cî'š…¢^êu˜³,lÅ3{QÅtœ¼¼!õx :6.ÃÏýÍi/yóNfÿæ»$ƒ"ʼ[Hf .ç)é—u£ëôH1ÙŠÛli¾ª3½Œ’x²ƒîf+0w¥(fŠ„€yõ->æq6â‚zz(5^Ñ¥‘¤§[X¼&àäZôy‚ ÑÆ9‚±Äz ‡ ˆãaÕZ³ÓñLû+NÑüD@zðö…ÁsV…ñ\ûÝps¨šÖ-5ÅSD]¬Ï$Qéú"ìá wgZQEÔUŒ64« ¿É®8oP©’x$U²Åè¬sÚª+Ò7eŽEiåäã®åsM—õ$·LÅèL+QÁl jr×Pµš+.¶Þ?uÚ‰çá+ñ•©bEJ¾ŠjÅ̶tîéb<— 0ì› ŒÜN+-­ åI·ç—(ÊTÎõþç%XK–S ]©S "«åн]½Šäé³êªâqî„Έå:Mg¨/ûe–õŰŸúÿ™¢ìmÍCyTç²² Eäy>ùò4+úÃAžMúCê|ÆBòË|"®iÖõQf ÝßÞ^¢Q»N¿nŠ6âLÁtSФ ýšöÔðþYŽ¢*‹) ²h)1f8¸„×> ¡j0N‡é88at]$'Ï„3®h[†º›ªü‹º‚j9›O^ê*µƒ…¬:Ç£îã†hò#Ax?…~†µ©Ð©Ó¿ã¥ñ\…—­$i»]œ‹?âêç“ô̪x{•WÈ–‚43[YɈ'’ˆ×ib>¶J¶bLL÷39Ë ( 4¿AXºñžoHXårÊSÐÄ•ѱŸi+ñs@j¡ ÍÆt52Ø'WQÜ^à‹3çz_R2§SCÉß-réçÖzæžX|PX¦ã,Dlõ™%ϵú×·lÙ J£)e‹SYü¢`ýå¦ Ùc°ä*n´Ã@s·Wó˱Sš0-Þ›ÝÑðiL>†´Üìò˪Í/ªúåì d¹œv}ÜO¾âÇÝVæšAU0wÀg§à¿v´½üë«Ëã6Yíð>h†Î:j™ãÂØµ~{ Þ•s' 1á+¯&ؘ¸ö¨>h]…ª|q Ø[¸KuðåEÝ*#ü¢‘ªqT5hŽt8 ‹3åLéƒód›ZŒAdÈ aŒåDQ1ŸÒ÷Sb’6»†akã´.¡ýr6¯Îú“r.*­sVYü+¨ÁJñËÕ^Ž…qƒÑ&`øÂ‘ƒT Sk– ¸þœjì W–½ÜþZbÓÚÇí´6g?}IÂ>@¿LýÇô#¡—ù‚ü|cÅh]¬÷Ç[GkÑÔU=‡Ä .ϳjŠ+möÓ6ÔA˜uAb×8Äí€g²ŒÕˆ•pð$3y`«\YÂPý©EÖÆ¡®uÈðn(¹ø²çWä^¶ŸË?.Š·Ùìˬ¬úçù| àø×¼ÿÊêÜÉiÄ Purpose of Hack --------------- Allows you to filter a region of text, in your sedit window, through an arbitrary Unix command line. What You'll Need ---------------- Nonething in particular. Instructions ------------ In your file of exmh hacks[1] (which should reside in the directory named in Preferences->Hacking Support->User Library Directory), add the following. proc jk-shell {t c} { set res [exec -keepnewline sh -c "$c" << [selection get]] if {![catch "set tndx [$t index sel.first]"]} { $t delete sel.first sel.last } else { set tndx [$t index insert] } $t mark set insert $tndx $t insert insert "$res" } proc jk-add-shell {t} { set w [winfo parent [winfo parent $t]] if {![winfo exists $w.jkf]} { pack [frame $w.jkf] -side top -fill x -ipady 2 } if {![winfo exists $w.jkf.l]} { pack [label $w.jkf.l -text Filter] -side left } if {![winfo exists $w.jkf.e]} { pack [entry $w.jkf.e] -side left -expand yes -fill x -ipady 2 $w.jkf.e insert end {sed -e 's/^/> /'} } if {![winfo exists $w.jkf.b]} { pack [button $w.jkf.b -text Filter \ -command "jk-shell $t \[$w.jkf.e get\]"] -side left \ -ipady 2 } } proc Hook_SeditInitFilter {d t} { jk-add-shell $t } [1] This file can be called "user.tcl" (or whatever.tcl, really). If you don't have one already, copy "user.tcl" from the exmh library directory and use it as a template for your own. After you do this, run a "tclsh" in this same directory. From it, do "auto_mkindex . *.tcl" to update your "tclIndex", then restart exmh. Usage ----- After you've restarted exmh, you should see a new region at the bottom of your sedit window, with a label that reads "Filter". Put together an arbitrary Unix command line (one that'll act as a filter), and enter it into this new region's entry widget. Select a region of text, in your sedit window, and hit the "Filter" button... Your selected text will be run through the filter you've specified, and replaced with the result. By default, the entry widget should come up with "sed -e 's/^/> /'" in it. I use this to put a leading "> " string on a range of lines, for example. To Do ----- Some kind of an "undo" facility would be nice... It would also be nice to add each command line, once executed by the "Filter" button, to a cascading or drop-down menu. That way, you'd be able to go back and apply and earlier command line to a new region of text, without having to retype it. The history of command lines could be made persistent, as well. Author ------ John Klassa exmh-2.9.0/misc/mafe/0000755000170700017070000000000013201227060013651 5ustar valdisvaldisexmh-2.9.0/misc/mafe/exmhmail0000755000170700017070000000010013201227060015372 0ustar valdisvaldis#!/usr/bin/wish -f wm withdraw . send exmh "Sedit_Mailto $argv"exmh-2.9.0/misc/mafe/mafe0000755000170700017070000005355413201227060014523 0ustar valdisvaldis#!/usr/bin/perl #use strict; use Tk; require Tk::ROText; require Tk::BrowseEntry; require Tk::Dialog; (%aliases,%distros,%dtags,%olddtags,%akeys,%dkeys,%nakeys,$ndkeys,$CDchoice,$CAchoice,$WhichBox)=(); @hnames=qw(aliases distros); @CADc=qw(CAchoice CDchoice); @BNames=qw(Distro Alias); $Defaultdtag="Undisclosed Recipients"; $UpperLimit=3; $MaxLineLength=80; $DefaultAddress=""; $DefaultAddress=$ARGV[0] if $ARGV[0] ne ""; $configdir=$ENV{HOME}; $configdir.='/' if ! ($configdir=~/\/\s*$/); open (CONFIG,$configdir.'.exmh/exmh-defaults') || die "Can't open ${configdir}.exmh/exmh-defaults\n"; while () { $BFont=$1 if /s*\*Button\.font:\s+(.*)/; $TFont=$1 if /s*\*Msg\*Text\.font:\s+(.*)/; } $DColour='grey'; close (CONFIG); open (MH,$configdir.'.mh_profile') || die "Can't open ${configdir}.mh_profile"; while () { chomp; s/^\s+//; if (!(/^\#/)){ $AliasFile=$1 if /\s*AliasFile:\s*(.*)/; } } close(MH); (%AliasCheck,@AliasFile)=(); foreach $key (split(/\s+/,$AliasFile)) { if (!$AliasCheck{$key}) { push(@AliasFile,$key); $AliasCheck{$key}=$key; } } # First, construct main window my $main=MainWindow->new(-title=>"mafe: MH alias file editor"); if ($#AliasFile>0) { $ShowFile=$main->BrowseEntry(-autolimitheight=>1, -choices=>\@AliasFile, -width=>22,-font=>$TFont, -browsecmd=> sub{&SwitchAliasFile($_[1])})-> grid(-column=>0,-row=>0,-sticky=>'nw',-columnspan=>5); $whichfile=$ShowFile->Subwidget("entry"); } else { $ShowFile=$main->ROText(-width=>22, -height=>1,-font=>$TFont,-relief=>'flat')-> grid(-column=>0,-row=>0,-sticky=>'nw',-columnspan=>5); $ShowFile->insert('end',$AliasFile[0]); } $CurrentFile=$AliasFile[0]; $oldCFile=$CurrentFile; my $BFrame=$main->Frame->grid(-row=>0,-column=>1,-sticky=>'ne'); my $help=$BFrame->Button(-text=>'Help', -font=>$BFont, -padx=>0)->grid(-column=>4, -row=>0,-sticky=>'e'); my $save=$BFrame->Button(-text=>'Save', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&SaveData}) ->grid(-column=>5, -row=>0,-sticky=>'e'); my $dismiss=$BFrame->Button(-text=>'Dismiss', -font=>$BFont, -padx=>0, -command=> sub{&Dismiss}) ->grid(-column=>6, -row=>0,-sticky=>'e'); my $dialog=$main->Dialog(-title=>'Unsaved Data!', -text=>'Blah Blah Blah', -font=>$TFont, -default_button=>2, -buttons=>[('Save', 'Don\'t Save', "Cancel")]); my (@ADFrame,@ADLabel,@ADBox,@ADEntry,@ADBFrame)=(); my (@ADComp,@ADInsert,@ADChange,@ADDelete,@ADSwap)=(); my @LabelNames=qw(Aliases Distributions); foreach my $ii (0..1) { $ADFrame[$ii]=$main->Frame->grid(-row=>2+$ii, -column=>0,-sticky=>'nw'); $ADLabel[$ii]=$ADFrame[$ii]->Label(-text=>$LabelNames[$ii], -font=>$TFont) ->grid(-column=>0, -row=>0); $ADBox[$ii]=$ADFrame[$ii]->Scrolled('Listbox', -width=>22, -height=>10, -scrollbars=>'oe', -font=>$TFont) ->grid(-column=>0, -row=>1, -sticky=>'wn'); $ADBox[$ii]->bind('', sub{&show_tag($ADBox[$ii]->get('active'),$ii)}); $ADEntry[$ii]=$ADFrame[$ii]->Entry(-width=>26, -font=>$TFont) ->grid(-column=>0, -row=>2, -sticky=>'wn'); $ADBFrame[$ii]=$ADFrame[$ii]->Frame->grid(-column=>0, -row=>3); $ADComp[$ii]=$ADBFrame[$ii]->Button(-text=>'Comp', -font=>$BFont, -padx=>0, -command=>sub{&Compose($ADBox[$ii]->get('active'))}, -state=>'normal') ->grid(-column=>0, -row=>0); $ADInsert[$ii]=$ADBFrame[$ii]-> Button(-text=>'Insert', -font=>$BFont, -padx=>0, -command=>sub{&InsertAlias($ii,$ADEntry[$ii]->get)})-> grid(-column=>1, -row=>0); $ADChange[$ii]=$ADBFrame[$ii]-> Button(-text=>'Change', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&ChangeAlias($ii,$ADEntry[$ii]->get)})-> grid(-column=>2, -row=>0); $ADDelete[$ii]=$ADBFrame[$ii]-> Button(-text=>'Delete', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&DeleteAlias($ii,$ADBox[$ii]->get('active'))})-> grid(-column=>3, -row=>0); $ADSwap[$ii]=$ADBFrame[$ii]-> Button(-text=>$BNames[$ii], -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&SwapType($ii,$ADBox[$ii]->get('active'))})-> grid(-column=>4, -row=>0); } my $DistroFrame=$main->Frame->grid(-column=>1, -row=>1); my $AddressFrame=$main->Frame->grid(-column=>1, -row=>2,-rowspan=>2); my $AddressLabel=$AddressFrame->Label(-text=>'Addresses', -font=>$TFont) -> grid(-column=>1, -row=>0); my $DistroLabel=$AddressFrame-> Label(-text=>'Distro. Tag:', -font=>$TFont, -fg=>$DColour)-> grid(-column=>0, -row=>1, -sticky=>'e'); my $DistroShowFrame=$AddressFrame->Frame->grid(-column=>1, -row=>1,-sticky=>'w'); my $DistroName=$DistroShowFrame-> Entry(-width=>26, -state=>'disabled', -font=>$TFont, -relief=>'flat', -validate=>'focus', -validatecommand=>sub{$SetButton->configure(-state=>'normal'); return 1;})-> grid(-column=>0, -row=>0, -sticky=>'w'); my $SetButton=$DistroShowFrame-> Button(-text=>'Set', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&ChangeDTag($CDchoice)})-> grid(-column=>1, -row=>0, -sticky=>'w'); my $AddressBox=$AddressFrame-> Scrolled('Listbox', -width=>30, -height=>20, -scrollbars=>'osoe', -font=>$TFont) -> grid(-column=>1, -row=>2,-sticky=>'nw'); $AddressBox->bind('<1>', sub{&show_tag('',2)}); my $AddressEntry=$AddressFrame->Entry(-width=>38, -font=>$TFont)-> grid(-column=>1, -row=>3, -sticky=>'wn'); $AddressEntry->insert(0,$DefaultAddress) if $DefaultAddress ne ""; my $EBFrame=$AddressFrame->Frame->grid(-column=>1, -row=>4); my $EInsert=$EBFrame-> Button(-text=>'Insert', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&InsertAddress($AddressEntry->get)})-> grid(-column=>0, -row=>0, -sticky=>'e'); my $EChange=$EBFrame-> Button(-text=>'Change', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&ChangeAddress($AddressEntry->get,$AddressBox->get('active'))})-> grid(-column=>1, -row=>0); my $EDelete=$EBFrame-> Button(-text=>'Delete', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&DeleteAddress($AddressBox->get('active'))})-> grid(-column=>2, -row=>0, -sticky=>'w'); my $EExpand=$EBFrame-> Button(-text=>'Expand', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&Expansion})-> grid(-column=>3, -row=>0, -sticky=>'w'); my $EContract=$EBFrame-> Button(-text=>'Contract', -font=>$BFont, -padx=>0, -state=>'disabled', -command=>sub{&Contraction})-> grid(-column=>4, -row=>0, -sticky=>'w'); ############################################################# # Now, populate the Aliases and Distributions ############################################################# &ReadFile($CurrentFile, $ADBox[0], $ADBox[1]); MainLoop; ############################################################## sub Expansion{ local (@newlist)=(); local ($curbox, $othbox)=($WhichBox,-1*$WhichBox+1); $changed=0; $CADc=${$CADc[$curbox]}; $hname=$hnames[$curbox]; $word=${$hname}{$CADc}; $special=0; if ($AddressBox->curselection ne '') { $special=1; $spword=$AddressBox->get($AddressBox->curselection); } foreach $key (split(/,\s+/,$word)) { if ($special==0 || ($special==1 && $spword eq $key)) { if ($aliases{$key}) { foreach $subkey (split(/,\s+/,$aliases{$key})) { push(@newlist,$subkey); } $changed=1; } elsif ($distros{$key}) { foreach $subkey (split(/,\s+/,$distros{$key})) { push(@newlist,$subkey); } $changed=1; } else { push(@newlist,$key); } } else { push(@newlist,$key); } } ######################## ### check for duplicates ######################## @newlist2=(); @newlist=sort {lc($a) cmp lc($b)}(@newlist); push(@newlist2,$newlist[0]); foreach $key (@newlist) { push(@newlist2,$key) if $newlist2[$#newlist2] ne $key; } $changed=1 if $#newlist != $#newlist2; @newlist=@newlist2; $$hname{$CADc}=join(', ',@newlist); &show_tag($CADc, $curbox); $save->configure(-state=>'normal') if ($changed==1); } sub Contraction{ local (@newlist,%inlist)=(); local ($curbox, $othbox)=($WhichBox,-1*$WhichBox+1); $CADc=${$CADc[$curbox]}; $hname=$hnames[$curbox]; $word=${$hname}{$CADc}; $special=0; if ($AddressBox->curselection ne '') { $special=1; $spword=$AddressBox->get($AddressBox->curselection); } $count=0; $changed=0; foreach $supkey (split(/,\s+/,$word)) { $count++; if ($supkey=~/([a-zA-Z0-9_.]+\@[a-zA-Z0-9_.]+)/) { $key=$1; if ($special==0 || ($special==1 && $spword eq $supkey)) { if ($akeys{$key} ne '' && $akeys{$key} ne $CADc && $nakeys{$akeys{$key}} <= $UpperLimit) { push(@newlist,$akeys{$key}) if $inlist{$akeys{$key}} eq ''; $changed=1; $inlist{$akeys{$key}}=$key; # print "1. $akeys{$key}\n"; } elsif ($dkeys{$key} ne '' && $dkeys{$key} ne $CADc && $ndkeys{$dkeys{$key}} <= $UpperLimit) { push(@newlist,$dkeys{$key}) if $inlist{$dkeys{$key}} eq ''; $changed=1; $inlist{$dkeys{$key}}=$key; # print "2. $dkeys{$key}\n"; } else { push(@newlist,$supkey); # print "3. $supkey\n"; } } else { push(@newlist,$supkey); } } else { push(@newlist,$supkey); # print "4. $supkey\n"; } } ######################## ### check for duplicates ######################## @newlist2=(); @newlist=sort {lc($a) cmp lc($b)}(@newlist); push(@newlist2,$newlist[0]); foreach $key (@newlist) { push(@newlist2,$key) if $newlist2[$#newlist2] ne $key; } $changed=1 if $#newlist != $#newlist2; @newlist=@newlist2; # print "$count ... ".($#newlist+1)."\n"; # foreach $key (sort (keys (%akeys))) {print "$key - $akeys{$key}\n";} $$hname{$CADc}=join(', ',@newlist); &show_tag($CADc, $curbox); $save->configure(-state=>'normal') if ($changed==1); } sub ChangeDTag { local ($tag)=@_; local $name=$DistroName->get; if ($name ne "") { $save->configure(-state=>'normal') if $dtags{$tag} ne $name; $dtags{$tag}=$name; } $SetButton->configure(-state=>'disabled'); $ind=&GetInd($CDtag,%distros); $ADBox[1]->selection(set,$ind); $ADBox[1]->see($ind); } sub InsertAddress { local ($word)=@_; local ($curbox, $othbox)=($WhichBox,-1*$WhichBox+1); $CADc=${$CADc[$curbox]}; $hname=$hnames[$curbox]; if ($word ne "") { ${$hname}{$CADc}=&insertion($word,${$hname}{$CADc}); &show_tag($CADc,$curbox); $ind=&GetInd2($word,${$hname}{$CADc}); $AddressBox->see($ind); $save->configure(-state=>'normal'); } } sub insertion { local ($substring, $string)=@_; local (%tempy)=(); $substring=~s/^\s+//; $substring=~s/\s+$//; foreach $key (split(/,\s+/,$string)) { $key=~s/^\s+//; $key=~s/\s+$//; $tempy{$key}=$key if !$tempy{$key}; } $tempy{$substring}=$substring if ! $tempy{$substring}; $string=join(', ',(sort {lc($a) cmp lc($b)} (keys (%tempy)))); return $string; } sub ChangeAddress { local ($word1,$word2)=@_; local ($curbox, $othbox)=($WhichBox,-1*$WhichBox+1); $CADc=${$CADc[$curbox]}; $hname=$hnames[$curbox]; if ($word1 ne "") { ${$hname}{$CADc}=&change($word1,$word2,${$hname}{$CADc}); &show_tag($CADc,$curbox); $ind=&GetInd2($word1,${$hname}{$CADc}); $AddressBox->selection(set,$ind); $AddressBox->see($ind); $save->configure(-state=>'normal'); $AddressEntry->delete(0,'end'); $AddressEntry->insert(0,$word2); $EChange->configure(-state=>'normal'); } } sub change { local ($substring1, $substring2, $string)=@_; local (%tempy)=(); $substring1=~s/^\s+//; $substring1=~s/\s+$//; $substring2=~s/^\s+//; $substring2=~s/\s+$//; foreach $key (split(/,\s+/,$string)) { $key=~s/^\s+//; $key=~s/\s+$//; $tempy{$key}=$key if (!($tempy{$key}) && ($substring2 ne $key)); } $tempy{$substring1}=$substring1 if ! $tempy{$substring1}; $string=join(', ',(sort {lc($a) cmp lc($b)} (keys (%tempy)))); return $string; } sub DeleteAddress { local ($word)=@_; local ($curbox, $othbox)=($WhichBox,-1*$WhichBox+1); $CADc=${$CADc[$curbox]}; $hname=$hnames[$curbox]; if ($word ne "") { ${$hname}{$CADc}=&deletion($word,${$hname}{$CADc}); &show_tag($CADc,$curbox); $ind=&GetInd($CADc,%{$hname}); $ADBox[$curbox]->selection(set,$ind); $ADBox[$curbox]->see($ind); $save->configure(-state=>'normal'); } } sub deletion { local ($substring, $string)=@_; local (%tempy)=(); $substring=~s/^\s+//; $substring=~s/\s+$//; foreach $key (split(/,\s+/,$string)) { $key=~s/^\s+//; $key=~s/\s+$//; $tempy{$key}=$key if (!($tempy{$key}) && ($substring ne $key)); } $string=join(', ',(sort {lc($a) cmp lc($b)} (keys (%tempy)))); return $string; } sub InsertAlias { local ($curbox, $word)=@_; $hname=$hnames[$curbox]; if ($word ne "") { ${$hname}{$word}=""; &FillFrames($curbox,%{$hname}); $ind=&GetInd($word,%{$hname}); $ADBox[$curbox]->selection(set,$ind); $ADBox[$curbox]->see($ind); &show_tag($ADBox[$curbox]->get($ADBox[$curbox]->curselection),$curbox); $ADEntry[$curbox]->delete('0','end'); if ($curbox==1) { $dtags{$word}=$Defaultdtag; } $save->configure(-state=>'normal'); } } sub ChangeAlias { local ($curbox,$word)=@_; $hname=$hnames[$curbox]; local $ll=$ADBox[$curbox]->get($ADBox[$curbox]->curselection); if ($word ne "" && $ll ne "") { if ($curbox==1) { $dtags{$word}=$dtags{$ll}; delete $distros{$ll}; } ${$hname}{$word}=${$hname}{$ll}; delete ${$hname}{$ll}; &FillFrames($curbox,%{$hname}); $ind=&GetInd($word,%{$hname}); $ADBox[$curbox]->selection(set,$ind); $ADBox[$curbox]->see($ind); &show_tag($ll,$curbox); $ADEntry[$curbox]->delete('0','end'); $save->configure(-state=>'normal'); } } sub DeleteAlias { local ($curbox, $word)=@_; $hname=$hnames[$curbox]; if ($word ne "") { delete $dtags{$word} if $curbox==1; delete ${$hname}{$word}; &FillFrames($curbox,%{$hname}); $save->configure(-state=>'normal'); } $AddressLabel->configure(-text=>'Addresses'); $EInsert->configure(-state=>'disabled'); $EChange->configure(-state=>'disabled'); $EDelete->configure(-state=>'disabled'); $EExpand->configure(-state=>'disabled'); $EContract->configure(-state=>'disabled'); $DistroName->delete(0,'end'); $DistroName->configure(-state=>'disabled', -relief=>'flat'); $DistroLabel->configure(-fg=>'grey'); } sub SwapType { my ($curbox,$word)=@_; my $othbox=-1*$curbox+1; my ($hname,$oname)=($hnames[$curbox],$hnames[$othbox]); if ($word ne "") { ${$oname}{$word}=${$hname}{$word}; if ($curbox==0) { $dtags{$word}=$Defaultdtag; $dtags{$word}=$olddtags{$word}if ($olddtags{$word} ne ""); } else { $olddtags{$word}=$dtags{$word}; } delete ${$hname}{$word}; &FillFrames(0,%aliases); &FillFrames(1,%distros); $ind=&GetInd($word,%{$oname}); $ADBox[$othbox]->selection(set,$ind); $ADBox[$othbox]->see($ind); &show_tag($word,$othbox); $save->configure(-state=>'normal'); } } sub GetInd { local ($word, %AliasOrDistro)=@_; local $ii=-1; foreach $key (sort {lc($a) cmp lc($b)} (keys (%AliasOrDistro))){ $ii++; last if ($key eq $word); } return $ii; } sub GetInd2 { local ($word, $string)=@_; local $ii=-1; foreach $key (sort {lc($a) cmp lc($b)} split(/,\s+/,$string)) { $ii++; last if ($key eq $word); } return $ii; } sub SwitchAliasFile { ($CurrentFile)=@_; if ($CurrentFile ne $oldCFile) { $result=""; if ($save->cget(-state) eq 'normal') { $dialog->configure(-text=>"You are about to leave $oldCFile without saving the changes that you\'ve made!!!"); $result=$dialog->Show(); &SaveData if $result eq 'Save'; } if ($result ne 'Cancel') { &ReadFile($CurrentFile,$ADBox[0], $ADBox[1]); $save->configure(-state=>'disabled'); } else { $CurrentFile=$oldCFile; $whichfile->configure(-state=>'normal'); $whichfile->delete(0,'end'); $whichfile->insert(0,$CurrentFile); $whichfile->configure(-state=>'disabled'); } } $oldCFile=$CurrentFile; } sub ReadFile{ ($CurrentFile, $ADBox[0], $ADBox[1])=@_; local ($tag,$addresses,$dtag)=(); open (FILE, $CurrentFile) || die "Can\'t open the alias file \"$aliasfile\"\n"; # First, read the alias file and assign the addresses to either # one of two hashes, depending on the form of the line: # (1) %distros if alias: aliasname:, email1@b.c ..., ; # (2) %aliases if alias: email1@b.c ... (%aliases,%distros,%dtags)=(); while () { chomp; if (/^[^:]+:/) { if ($tag ne '') { $addresses=~s/\\//g; $addresses=join(', ',split(/,\s+/,$addresses)); if ($addresses=~/^([^:]+):(.*)/){ ($addresses,$dtags{$tag})=($2,$1); $addresses=~s/^\s*,\s+//; $addresses=~s/,\s+;//; $distros{$tag}=$addresses; } else { $aliases{$tag}=$addresses; } ($tag, $addresses)=(); } ($tag,$addresses)=($1,$2) if (/([^:]+):(.*)/); $tag=~s/^\s+//; $tag=~s/\s+$//; $addresses=~s/^\s+//; $addresses=~s/\s+$//; } else { $addresses.=$_; } } # in case there is a $tag $address pair which hasn't been put into # the appropriate hash... if ($addresses=~/^[^:]+:/){ $distros{$tag}=$addresses; } else { $aliases{$tag}=$addresses; } close FILE; # assign each email in the %distros to another hash has whose value is # the %distros' key (sort of like a reverse hash) foreach $key (keys (%distros)) { $count==0; foreach $skey (split(/,\s+/,$distros{$key})) { $count++; $email=$1 if $skey=~/(\S+\@\S+)/; $email=~s/[<>]//g; $dkeys{$email}=$key; } $ndkeys{$key}=$count; } # do the same for the %aliases hash foreach $key (keys (%aliases)) { $count=0; foreach $skey (split(/,\s+/,$aliases{$key})) { $count++; $email=$1 if $skey=~/(\S+\@\S+)/; $email=~s/[<>]//g; $akeys{$email}=$key; } $nakeys{$key}=$count; } &FillFrames(0,%aliases); &FillFrames(1,%distros); $AddressLabel->configure(-text=>"Addresses"); $EInsert->configure(-state=>'disabled'); $EChange->configure(-state=>'disabled'); $EDelete->configure(-state=>'disabled'); $EContract->configure(-state=>'disabled'); $EExpand->configure(-state=>'disabled'); # $ADBox[0]->delete(0,'end'); # $ADBox[0]->insert(0,(sort {lc($a) cmp lc($b)} (keys (%aliases)))); # $ADBox[1]->delete(0,'end'); # $ADBox[1]->insert(0,(sort {lc($a) cmp lc($b)} (keys (%distros)))); } sub FillFrames { local ($num, %AliasOrDistro)=@_; $AddressBox->delete(0,'end'); $ADBox[$num]->delete(0,'end'); $ADBox[$num]->insert(0,(sort {lc($a) cmp lc($b)} (keys (%AliasOrDistro)))); } sub show_tag{ local ($tag,$curbox)=@_; local (%list)=(); if ($curbox==0) { %list=%aliases; } elsif ($curbox==1) { %list=%distros; } else { %list=%aliases if $WhichBox==0; %list=%distros if $WhichBox==1; $tag=$CAchoice if $WhichBox==0; $tag=$CDchoice if $WhichBox==1; } if ($curbox!=2){ $WhichBox=$curbox; $AddressBox->delete(0,'end'); $AddressBox->insert(0,(sort {lc($a) cmp lc($b)} split(/,\s+/,$list{$tag}))); $DistroName->delete(0,'end'); $EChange->configure(-state=>'disabled'); $EDelete->configure(-state=>'disabled'); $AddressLabel->configure(-text=>"Addresses for \"$tag\"") if $tag ne ""; } if ($list{$tag}=~/\w/) { $EExpand->configure(-state=>'normal'); $EContract->configure(-state=>'normal'); } $EInsert->configure(-state=>'normal'); if ($curbox==1) { $CDchoice=$tag; $DistroName->configure(-state=>'normal', -relief=>'sunken'); $DistroName->insert(0,$dtags{$tag}); $DistroLabel->configure(-fg=>'black'); $ADComp[1]->configure(-state=>'normal'); $ADChange[1]->configure(-state=>'normal'); $ADDelete[1]->configure(-state=>'normal'); $ADSwap[1]->configure(-state=>'normal'); $ADComp[0]->configure(-state=>'disabled'); $ADChange[0]->configure(-state=>'disabled'); $ADDelete[0]->configure(-state=>'disabled'); $ADSwap[0]->configure(-state=>'disabled'); } elsif ($curbox==0) { $CAchoice=$tag; $DistroName->configure(-state=>'disabled', -relief=>'flat'); $DistroLabel->configure(-fg=>'grey'); $ADComp[1]->configure(-state=>'disabled'); $ADChange[1]->configure(-state=>'disabled'); $ADDelete[1]->configure(-state=>'disabled'); $ADSwap[1]->configure(-state=>'disabled'); $ADComp[0]->configure(-state=>'normal'); $ADChange[0]->configure(-state=>'normal'); $ADDelete[0]->configure(-state=>'normal'); $ADSwap[0]->configure(-state=>'normal'); } else { if ($list{$tag}=~/\w/) { $EChange->configure(-state=>'normal'); $EDelete->configure(-state=>'normal'); } $EInsert->configure(-state=>'normal'); } } sub SaveData{ open(OUT, ">$CurrentFile"); foreach $key (sort {$a cmp $b} (keys (%distros))) { &splitprint($key.": ".$dtags{$key}.":, ".$distros{$key}.", ;"); } foreach $key (sort {$a cmp $b} (keys (%aliases))) { &splitprint($key.": ".$aliases{$key}); } close(OUT); $save->configure(-state=>'disable'); } sub splitprint { local ($key)=@_; if (length($key)>$MaxLineLength && $key=~/,\s+/) { $clength=0; ($first,@subsequent)=split(/,\s+/,$key); print OUT $first; $clength=length($first); foreach $block (@subsequent) { if ($clength+length(', '.$block)>$MaxLineLength) { print OUT ", \\\n\t$block"; $clength=8+length($block); } else { print OUT ", $block"; $clength+=length(", $block"); } } print OUT "\n"; } else { print OUT "$key\n"; } } sub Dismiss { $result=""; if ($save->cget(-state) eq 'normal') { $dialog->configure(-text=>'You are about to quit without saving the changes that you\'ve made!!!'); $result=$dialog->Show(); &SaveData if $result eq 'Save'; } exit if $result ne 'Cancel'; } sub Compose { local ($addr)=@_; $addr =$AddressBox->get('active') if ($AddressBox->curselection) ne ""; system("exmhmail $addr &"); } exmh-2.9.0/misc/mafe/help/0000755000170700017070000000000013201227060014601 5ustar valdisvaldisexmh-2.9.0/misc/mafe/help/mafe_addr.gif0000644000170700017070000005605013201227060017200 0ustar valdisvaldisGIF89a„ÔÞìäæäÔÚܼ¾¼´ºÄôúüÜÞäÜâì ŒŠŒ|†œüþü”ž¬¤¢¤œ¦´ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!þCreated with The GIMP!ù ,þ $Ždižhª®lë¾p,ÏôÜ7€ç{ óµ pH,ȤrÉ$úvº(Nðœö~8,O×ìz¿à°xLžU¡èÞ9˦òÜÖë­L¯Ûïø¼‘Š…?µ~nZRlilX:~ZzŒŽCRZk~<…€j–”œšhT‘¡¢£¤e7–—…o†;Šk„|qVƒj?¥¸¹º»,ip‰¬§‡¯¶r†°ª¾l¼™ÃkÑsÍÔÕNʬ²Ù©±•ÇÙɨ9¦µh”ÐÝê[ÒÖðñ)Ñ®«ÅàUõÈÞö³ÊÉ?°|a·nÓ²nÁúƒ@žÃf°¶Ý+äêÙ¥ZçÂhÌÓ-$íBC¤F*lþñ½{ÈR”J‹ë~óÔà°t®€T%DãËOìú¬ (ç‡Íi-“âñG­ŸHä(Th«¨1w.‚AÐRJJ'.ìx,âÁ°Ó¼^½gà€Ò·$ ê̘§°˜ØT%{n2"J›'?…ùÖ¢ª 4ð=ºÜÂUúS[Ù«ta^ë“ÓÃU8vM4·`$+Ÿ#”ri•쨈<9)ç‚û4ŸN㚤NµøÄ•ìvTjÍã·q·)‰q9MØ0÷÷•q¶äÚòFzö–:+háϵþô}·¹ÙíaIªßÎ}÷Ì›¥¿ µ;«m±gÏ;”3Q˜© –h¯Ý•Ó]ÿþW i .CWBܼ–΃ ÞCÎ×éÇ VÅ}7\-úÜWLUL}E?DÛt]q8œ‡E6`b*ªÄbŠÃX§á†Æw˜iЄÔ•é%Ms˜œHÞv‚­‡œ“ܶW‚q %a"˜ŠŽ;–¢d‘*¶¶•™ÈßN~y$%t`Ї XÈMåÔ˜DÂ'¢`ä×¥Kìe£l~v¤sÆ ˆ¤q&â“-þyQâcP¢þȷ扴í 7ä8ÙœOa9¤œuâé c%hÕœP²'çe‚*Ç…ÇyúL&\jzGƒ&ZãNîe•&ivJ㥪¶Ii‚‹‘Øä>VJgIþª’«®MÜÖ£Lu¨Ï„†Ãàæ™¹ÐzÖjõÆ[TÈâ§².g£Xe `S3Ö£'¶óÔ+ª›Ó£`kÀÊ„{Àl=0 *±ìñ5#¨Ñ>ëX±â¦ŠŒÖ³¬ÁLÊ5_¦3d¤‹ˆOMŒªË#ŸÉŸä–›cž»aÀÂáú“R‡¦XѺ Ê#ƒºáå™ó\¡Š×ºo\‰¬ËúÌ(ú9Ë‘Åô03<›»ýD«¥º†ýjuróò…mgöbtr©OÔ+°»¦Pc|©`6;"§tšeŸm… 15‡KèšMùÂèFVsÏ5KÜù þŸOùÚkáxhz%ŸújIÛjç·´R|©Lòoß,S›Êtÿm™¾ Òš,Ź›9æ83Œ|[;ì9òšƒ ºô‘AO.ØÖA¬ŽTO< ²9åÄmGµ×̬GÜ‚î'›i§Ÿ«j)$hBv^ëVæ7;.9è8ÃÐ §½±YGsàÜØ@7›f./›Vë8Ö¨–±op¿À È^Ç-| M(|+:¢¥Œ+^结e„›>™Ï…3Y–hÖ9rP6åbÍ%±p1ïs?`ä~8Ä!²J@4¡­êó¥h[¬9á»4èD&F !A©r3V%}#Ëþ_™º§42FÐh¬ Ø?ɵQy‘i Í¥=æAŒyq¤#Ù®g®}ìihtay\æ+½PY¥KÃíD8÷1Å5²"acÞ)I±D¬ÒŸ× ÑÆÆ! Ìœ'øÀ‡I¬qý3e*óÈJ– «k“¬`EÔ¬§¨-#HÔV&å5Åud(.ôã ‡âwž Y±A1œÀ BEfêÒS««!UÉ0tцFÝè€Ø¹²ÕÌ:‘ WÒVóÂøm,utBݽ¼8#ñ©ii!ã¡ ¶hFz>ÊWåôIé=¬Œñ{Ýð¡¹8P=ÞQ;£B JPí!”¡‹•?wÈFº#5_<¤þ§µ \žo\œÚï®èAa¾’‚õÆ+ñ§L‚À¯áê;ŠRA¦•iM¯¢SK44éŠJ:­3m°Œü!'LòÇKÁ-Rk )!Œ EtrÑ, &ð„Ç‘. XyZ¨:Vƒ.ô¡emàXÓÊ9ê,¬rli‡iU°þfNxKÔ¶C¾óXÊÐ!ɘTØÀ²'Ú¨íIØ@]%dSƒC_”ÐÛL¶ uŒlúÐ'®."2“F•r KŒ*™PC™EºÏßmr„ZÝ^,SJ¸Ù ´øÂ+›Y±B´™Å¬f ZPƒˆ,± šWÜò¾|¢6Bn³TþÁÁ%z3~C1Ï F¹¶…ëìÝìç7J1îb/Z‚\¿’ôÚýŒÆZµØ»¡W"{½çTë»8áLrÍ*cë&ue÷W\cb[ ZÞU@²8 ^…QѦË^¦h›:z ©Féªe´b1åàYô‘Š“9ñ+4]Í’ºÄäj†ïØw-GáÚÉÚñÞ¶¨D†Lä"ùÈFvÛê¥U\Ñf¥—,˜TçW0ÒšXÉ0ö«‚´¨Y ÌXNSg¿ÜÝCm±/áù*}×ìe-Æ H޳œ  €ô1«®Ým®üÜîºò³!ÍœMèBúЈN´¢þÍèF;:Î2FJ†LÙJ@ ØF}©Æ%“‹Å µ”Ÿ$IcÕ¢–NµªWÍêV»úհ޵¬g½T'D]•¥´d*VL3GŸ2®*Sú÷³tûÀµ<âj£‚jÙ˜ËÙÎö­´yMíi[»ÚÏÆöµ·mn{[ÛÞˆ6¸¿mmT÷RFXеl.;œÙ(`Öݯ’ñ$©5~º±!]A¼Ô˜›Ö”]'ÀNpèüÆN÷kÒ¶³cáë«„(%ÏÝÛÿÜ êz#¨˜JnÝ~›(_PáäáN9Ê{¥ò–¯Üå0yìbNó—Û\Ø5ÏùÍQþ‹ëüç<÷7AKnþçè:®«~w ™z#85ÊQÍÔ«ÅåfRèß osÖ·>ëòœ‚\¿Á¿ V/\Ò)’0­=îu™ÍoŽ?«0€º`wÀ€׉ºÛïuÏLl}OݤèðWŽâ˜ï‰øÅo°ñg|áñ*yÇG~«•¿üåI®_’å© ÈSF߀”>ÕJ—ß ì·Þû zçÁN1ûÖÚžP³§ÂÜ@€5]\èø¬hDËé ¿¢Éh|•Ìë}U¥à8àôî0Ûm[±¦“å€XÞVïwpwÄÞ*³¹Ãu0þÔ^¹_}78ì ²œÁÇw”ò_û˜þæ«ô·âµ•nhòL‡j§1p6j€}—og_ôvTUàiÊñ—µií'…±÷%x3vÇTE§"UVWó!´Ã]kfB±‚…TТ‚M}ß…ÓwP 1kWg¸U1¤ýÃq7°8 wxç wwwî÷„…€g~~Çb;P{“p…KXwðW{½gtƇH™ÀrÄ'€g¸v–†ýk•”µÆ²c!b‡€×§Y¤wz @}§÷n Oú‡‚ä #P—ç—`˜„Þ~ñ7…Œè~Œ¸ë±{=‰ì{Ç~qøcµe(á\D…bœ(KMUuþŠ9VZ£Xа¥8ˆ7k kÀ‡8°‡7p‡¦7gAž÷‚Öµ[%öG„ „æWŒ !‚(‚Sè70~Ü“ˆˆHBׂë²DJeƒØˆ%ØÛˆ‚fæÔhcáøÑ@x°ˆg.{Xz h}³Q}㇤sZ¡uùñzϨ €7KX‰†f> ‰K(… H‰™˜ Їîál8†h˜qiT]F[ÊG¯hVk¨öŽT}{x}¸ˆ}A(P¤?õÐ:’a]¢{ˆxG‰š( ”˜„|¥“ä—“í—wa(„·Šü‡q¤ˆŠõ§’¡HŠä”” ¸/þ܃”-B€n0‡†Á8”–€7àŽÂå€J‡q®aMy3×±ZÊHw¸ûx–³×x‰ûX•I{ˆ{í§9 |¾(*)$–âè‚&¨6(rÉf@Å|¾x‚b‡\Tgv³øƒ[)’ Yz p’-–G](ƒU~÷™ígwQØ„8P~¢)~” ‰€ywŒ ˜w6©…B7Y錩†Y|‹r/p8‡«à›ŸÅææ}—1Ó÷˜Ôg.$Y}d‹8Cž8ŠV‚5]¡R-rÉ5"ÆOÁ “ © æf¹µ”Û •¬˜žE¹”ê‰ è¹\±ä”å‹ “Ïgnd%þ\“e˜¦XióWW©>$@+qgcP%r·”½çš~ƒu='~yæ(ƒÐT˜Ê2"˜*xÝy¡Ç€ƒÑuëH\h5t'—„„|©õKµ£_A•(ŸŸÉŒ›ÈW‰¢˜r›<Ê›çÖ£ÁãYÄã„§£XqŸ—…tEž  a´KÞW(3<†8z8«"ÙØC©x‡%Š”w”ìé-cÊžd'¦)v;ÉRDÉУGK ×ãµDi&DóD )I)ÉÇ‘mc˜¢‘•öUd–%5˜ÝÈ—Ú¨ªXuŒj%Q‚KºgçT6d¶)o‰ÐŸ-•BRþ ¿`ˆ‰*êdKVº5aJ $Gžø7T_‘@ª›ïE«µò&åp6t¹ÔeoZœ¿Æ‹©$L‡/+jÇ¥ †·K§:>YÕZ6­ÔZ­Öz­Øš­Ev«Z☪!˜Éª„2_€Œ(àºZ,cI:ø’›vð¯ò:¯\çP_44÷‰iMŠiüúnýº¯ûª¯ ­åv|z~Ô.tÕwª£¦ ä6nݦGâ±+±ë[âV±Û±Û±ß)f$výª¯&˯k²û:¬ñ5Š:.çêf3hc/‹*é8bôš³:»³<ik8oUVAë nÅPÍeaü•, 4¥þŒtªúÕ\ä‘Wq©Òª­V{µX›µZ»µÙÚq˲Y3€†õ¬éR!×tV²lÛ¶nû¶p·r;·t[·v{·x›·z»·|Û·ôw2J™¡ÇYªTÚ˜û1ä9Ž)ˆ§c Á°¶M¹þ*¹”;¹–[¹˜{¹š›¹œ»¹žÛ¹ û¹¢º¤;º¦[º¨k¹% °ÿв}·²¸_ibF8g:?ºdטç¸} ²Àû»Â¼Ä;¼Æë±DVp5±;t-Gd}”¢La‹aí`oW¥¥¥ƒTФ$Ú³â;¾ä;pì–³Ðû‰PJjS½Š81µy5þk „Ì›¿³mú›¼ü»¿ýû¿þÀ À<À,À \ÀÜÀ œÀ ¼À r ÀrhLœÁp¶Ž¿*ÎÄ2‹LÙ§¸TUv·«6!ú\k‹›åÛÂ.üÂÈŠ)¹É>é˲ÀBZ,i»¹»|øEzõÁ†dN÷{½UU©E|ÄFœÄH¼ÄJÜÄLüÄNÅP<ÅR\Å8·½)(Ÿ?½ •K £Õ+(µ„$ëê†SåQ­çoàëu0ÜÆn̳I,F" QÃ/ä¨~d®çjT‹‚‚˜cv³£j»}4’¸†|a¤Š<‡œÈŒŒÈ‹\ÈüÈŽ,É•ÜÈ‘ŒÉ”œÉ“lNàþœù÷¦ €jö*eÆL!\¸N[ƒÏ"^,”¸%ì +l«¸º›¶LË3œËµZËFÂT ¦f7žMóË% ÊšHè–®6\>) ]°@g ð‡ºì£·ÌËÖ<ÍՌ͸LÊf޼‘« O=,O1Ûyç^° X„a¬S× ³ŒvÿyWñ<®~%ÏTUEöŒÏôœÏõ¼Ïþ<Ï}ÏýÐ Š¬ûÖ‰b7Êõ{_;Õ{»U2¿†‹p9èpÐ Àï»ËÚ|ÍÝÑÔ¼ÍG“Á”ž¬$¸ë¹§ÿUÎÕY ÃbÖÌ.…vïŒÌ ÍÓÍÑ; Hdá¡;zûÒ2Xl¢Ãþ2\€ñKµæ5RDC k{´ÙGÇô2ÇdÕiKÕX]ÕåuÕ]Õ^­Õ_ÍÕb]ÖabÿtÍßœö4ßEhFÂÝùq2šƒTò½Bý×9}Ó~ÍÓ:]c`÷žµ6Êç‹kÞ§q„+¶0²¥>F¶¤~ŠñÁ0ÄÜüÁ|ÝÓ} ØÙ¶|*@-&ÈŸ¡æ|°&°gëeì¬Ã¬Â»ø&ˆ:ÐÍ϶ýϵÛúLд½Û¹ÍÛ· ÜŽõ×£ ¢—=5Ë´…ËÇD,p ¿Ñª?­ÔÍÙÖíÙ½ÙØ½¡V¦W¬ €¿2œÒDL–(@eåã,L$µ¯ÝŽª‘±MþuÝš]ßMß÷íc‹š˜;PÜZ•5lv¥äl5B¶Î]Ìǽ‚\kôˆÂrÖ`ád á.á[}ácáfmáÞáž [I|à-ZNÃYø¸Ø­ý2O”AÌz۸ž5­Õ½Ý4®Ý6nß¶ŠÂƒíÝ7PÜš*õg°GmÝwh“â6¬àÖÕ¸ r5Žã×}ãùMãÅVŽu%CzÒ|Åô2Z×ÖËå2Z—ΜÔx}4yáÛlÞÛnÜ¿çmçs®ÛonçpÞÖ{Ýþ­×¹éQzLàÒƒÒÊ¢8‚¢L~XRŽßŽåPžÙ }2¨¸ £mÁSýÚþkçÍâ#¬BI½HK`h°ÂüËéSžêO>‘õÈßÑ0}~n­(H9Lä)θ¤=Î1ºi¼ïŒ'AÃá^áÆ®áŽìÄžìÎìÅŽá@«6ÌÑÛ Ìwß­Ü" Ú>;7;¬¨)¬f:ø•Ý®êÞêçÎê4%;îzŸpªãæ ¶ÚÎØAEÄÀÙ/.ÖÞvBœ»(Õ\½ê‘®î_ðÍ—Ö¾8í\¬©X2LÚ%Ié­ŠëÁÞÂÓ‘çfêå.Cr~çÂýñOçòx^ò ¯6¾,|:z^vÜyl(à ³ýxóÌŒ¶`etô(.Â)ð>ŸîôÝœIþO ] \öcN¶ØËêòÌdæuµ„šgŸîo±½æ³Šîæ¾õZßõÂ÷êäz8ðNæî>é]ï²Y«‡äË»Dñ¦ š¦Üøì;ìvìu÷t¿÷ÎÞ÷SK·©ƒL=®Š„âaîÒ£ò³e>£žˆ©àë#3Nð?Ïõ”Ÿã<Œ”,x3-ßä¡èÒ–°ØàØpƒdè4ˆëWC ^ù^ô–ûhå$ø¤Üd‡©§õæ$œÎsÍ­N+œ¥ñY?Û"ü&Oò'?òu¾üÈò³TÍR0ö°‚†POP‹-¶¹¸÷ª»lø÷²ú*ôäû®ãj¦ë ëÇ þÄšNâ‡0ϽÌT/äà[Šï'i~Ã`vùæ_þ IŽ¥ˆ¦èY¶¦ú®n\«‚:ínø!PÖz7oÀ嘥$*•*{ÉžS†rnYM-ì#áZ…‚»§ZåÒ›<‹¯Ýó»=Çïõr]Ÿàß` á¡a"Ý""c׋˜Ød%ÊPA@V›—'¥Õ^ÔÔÔç©Oè•—QäéI–RÉ™Â爚Œ.Û.j/å쯥p0¯±ï10ñr²$ðZWtJkJfN,ö‘ôìäh©)ÓËø$§eå9´ÜÞ3ŽÀÙ¦òò}=þpò¾~±?3€üþå«G®ŠŽ„¨h B­þS!Ij".J˜WÝ’¬xø03æ •£…Fà²Vªl™òå4—1aâ’Y“溛3wêì™ó'KœAy•Éna@PÕ„Ù–ƒ`º¨(,^ä¤ÑF©"µ)-¦–šG^¡’MÚo¬Ù²Ó²]ëvnë=eš‰^\Ÿr¯Î€*8!rÓ)÷è‰líŽÎ…Z`-Â#s¹E‰¶òeËg7«ÕÜylã„p•ú½Ææ–è–"¿]¤ÂµR¡Ð%†åe4“ZAbÔ»‘"ྠ§ûû8qáÊ‘On’—œÏ]s­öô§ ÜÑÓÕWœÆG×n{肋Šwf÷ÜÖ=æþö™ç˯Oк°N ÷°ÖÔ“2è†8*tW € Ntƒ‹åå`È ›1ÏÑ÷™}ï]¨a†ñaø¡3tȦ;viÒM"‰ –Q¬µ†_|E…[á'ÕH£ ™`Í%”M?5”OD YdF*™$“@:9¤SÏpX“™Ü–•>|µàâ‹ö¨×S1.TŽd円~v›zÈ!ˆo¾eTˆQ÷Tu(†d'5+r÷"äÕµÊ`uÆÅ 7:X >†ÅÙæšnBú¨¤•rÚhø‰w¢ià}Ñ#¨èÌr wdBC£:‚ŠÊ˜©Á0¡ó¸sÁÕZœ­ÎéÚ¯¹þöŠ+°Ëízg!’ÁÉÐ]sÕ¶T¦úEj)4® ‹Ê²*Èž]yŨŽÂù­œ“‚+n¸óݨ…¢ˆY[Ú²‘®´[þ¨kîbE-EÌž!c)+2jR)Á<®¥#ºi¨Ä {⦒бb”'üIoKv­˜ŸN{­¶ƒqÁ-<>.ù$’(¹òÉPªÜrÊ.ËsÌýbI_&žfnŠj@‹ ;Ù^I¨”e2»K® ÊkÒ“é¢A²¾awÙ» 3§$ôIxÉÁøb(«1o§3^µPóŠá #L›…€îen´m¨Ã´`ŠqšºßTç>Æ} ?k˜ôE8Š8þ‰êû·îVŒÉQQsU¬Ü1·¹-f1Xž+ܱ¾—¬ˆýÄÍ;Ñ/ò%´9Êfe\Í¿Sݰ‚;´#눚öKQüYCÑ7 ?« <Ÿ6”¨>Ž$B1l\ìÔ!=æ0w¼¹¶Wµî•Hk ÄøºrB®°uÞ{…–Î3¢‘A†2"JˆÿòÇ?ýÉ2–ø»eÿj©ËÃðÑ,lW 8úÌx@ûØ‚Ú1‘d¦„‘N,¬"S6KRÖĤ›tôÂÞ ,t(‘€*†843uAÈ[e•áÉem3äÊP()ÏKVòš ëaƹ’Ïcys£¼Òؚɢþ.ËÑ6)±¬ÅŽ ‰Û$ç´ØE.Z±¢X´¨D1:ÉýÑ3Þ$O•â'¶&U"šƒ\¡J3¥G„«&6ç ÓzZfw]“ÆOa«‰`+'Fè8«éË‘Fu.¸õŒÎT¦ötjL%NW‘Å›"\˜Kø, JAZ#)%Xõ 4&þS† ¸“üf©V[æ—´tëZwÙVöàR¿Öˆ£C†mt±a]‰âè3µ6O¥'TiªØìpp“½û¢ŒòDÆ‚’$¥17¶.âùóììc”àGx"¶´M5íaöÐ'Š”SÀDQúò)¢br5uŽ¥òŠ&ج&!šþÁ¬F)zÑáf”¸=®p‹ËÍÛ‚NŒ'ÚÚWAƒ(¾b Ž3òiTR©­ÍÔBЧýnjËM›>2žTÒY#QÑSk]ö§@ &3…ÊŽøÎ† •`¬~ Yñ.µQ¯&y+]‰î‹Šsæ1k<¡S+¦Ün¦æ¢TT¦"®peë[çšá [XÃü 0}¹O`Ö—>%IÕØOÊ*½%l_=’–^ò7±6öo=µ¹>vÓ¹&b8 3=rÖÖ¤kD鵤å¼t)m­…ÉÁûßë°®emp YˆSªš­½).•~ì:Î&7 ±n‡Ü‰²9¸m6nr×üÁbuôBVþUfLe±/G˰¿õÈ'\¸[ÎÀ®m£¥²”û›h ’·²‹É©kñêFK¬—Y|6…ñ¥‘¢Žó¨Ïƒ•¬¼:ä)“Zш®]€óéLØJvhÀ å©«ÀºÅ…#ŒËªÔ¥ÉÃæ°¯ƒ-W`ûÃuµÔ]…YSŽÒ½åäuVrëg³Ô¬ôÀõL]ê(Ÿš7ŸcæÕ&íIeF÷¾®Sp_­Û`e#äÄÎ{ì™Ï Ënk»ÞÜž”•¹Œeô¦pˆ`<ãTjË¢ønǪ0U“ª´lîÍÊ•3œñ‡ÇY9™~&}üMŒ»î ²îƒ¶é'TNFè¶q|o{Ï­ÑæVþס³ÜÏ›zZ èY,DéÌ÷³ðf…´¼Ð”/ZåFWªYë0ƒT¡³ªïž.fUÏZKÄ‘ÈZj¯´ ûÂÅÁNl¯ÓnɶÁjèÓKÛ¶çC=¥ !(Pï+Ù^9ÞNoU;–ɽóÀË«U"?»ˆ*ÄõòÌwßQä}Ñ÷®÷È oúÞ”ÌCãïB2ñæÞñ«nGXjÿ“°ÐÞ…Ä+žúÕ»¹õŸó½\lŸºZçKºg­ÙZï¼Zr]zÎÚÆ»OžåE?~…ùøs!Å$ób6w‰ik̦MÚXZü#÷ô ù”7¾äë$¾¡R'„ŸŒÈþÛ§ëì¾z¶tª²v±Îå ‡øëö'{ØïŸü®i'ØÙ¥Î,çMÁÈ\§Ñ—âl× 1ÀØ]øEà÷q[c‘ß=Ž ´Ú0K¥yBîuɤ­›è]Ú0^h©ÇÍ@øM`ñåíí?•˜ºèȉ­ßà¤FòôÞR•ßAQì¯MªžëQë½^çÐǙәGH]Wùà  Ñ ™Õù †DÏðIà ~¡ Æ`7\ ”?¥‰ÓkàñœŸô¼Ÿ$ùn_!uŸ†! VSÒýÓÒ{‰_V‘[| Šé—ì„UâÍœfI´M/é_ÿEâ¯Mþ¢ØQ¢\˜Ù˜¤iž^=ŸiÞTÙÀÂÖ ©Ýñy¶ Þé¸'j`Γł "¦(’v,YöiÝãÍβ¢*ÞX¾éˆ ¾ÖÔ%³yYf…OlXŸ¦­TéÅsA”*!a&á6ÒÅÅñ\Æù!t‘Qyà—šûaW»5QJX~uac1â˜Ë-Ÿy¿b ™}¡Ø3àaœÀ!ô AÝÕ!BΣC®¢^\„¡,¢"3öÛV‘R^‰ ÒÂý 5ÞÌd@¢%ò_IîJJ"iýßÀàÅGü±á"•™ùã‹­TZ›E>$þBdxU`á\`ù!õõ£.ŽÔ3ŽÞIU]œ rƒã¥ 0ò$1Ò£c bÞ>¢áOè˜0}Y–Û9Öï¤Âç©Y6~#[v#7®¥[‚ …9♉ŽâW!ž‹)5òŽURe=âÐ=’!{˜ák…ÍÞ Èä.*`½¡Þî‰æ`ú$|ìáEvø(¥î}rLM>Zû-â¼5bš¤IV¢l’älÆfý`¢]i"»ÉGM0XBcõé`èý¥„ÈÃBÎÖfö¤rÞ‘+ ÞPŽ›Û­Z-ª_:Ž Éu”y“¹“-c*&gUj¦G­Ö•iåþŠZ„Î'@¦@Ú AÒ˜Æ<Ù¨íZZ†J\¶%\æ§7Þ§1¡8ím f$Øon¤Èu¤c}$-]M%g>èr¦H¾ó)¦¤Ñ >Fc€en霆òœ|ýãv&¤,$f6$„†gŠÒŽgN$hŽ:‚ d*å‘1eÕž€¹¦Ÿõmþ¨miJžd†á&²é&ÚÕNzÃ-ªØ2‰%Ü‘%q.¨NËwŠçŠ‚'ê}›sæt"“à "bŸõÛ^‚ÌGø¥v6fTú F¨–Æiå%_VÑV2&H:¦ üfýÕ(>Ÿ:e•ŒÞêç[î§¡j#b ³½cVþd(ØÞÎH^VjÚšïM)wÅ£`b)œz*¥&ÍAšóS©¦Ð°gŒ'’Mãš Ïe®›ƒ~j–‚*3´h ¾ès¹á :ÞjÊg”f'k¥ 9¢’im*+2«é± ’ `'¾Û'¶§Í¼çÖ-`™@“qîd­†+­vHs:8æ@E2a )ᡎ†’àŸ&èA.wj–±ªè¸âkiaeá$ã…îÞŽT³]špz(Ö€¨žµÎÐÑçX ¢>ì¡F¬¢æg8âÛ&Ò€v™~Þ2BT娦æ¤6蕊«¾&fˆª‘êVªÛ©.*\Ú“¦Ÿ¨pšˆþb4þ™¨¬–l¾¢¬­BÛT¹èª|é²|Ñø•cž){¥i.æÚüá#>+‘Ví²ªd³ÖL´¶ä´(?\]Ò*íʼn"‚6‚öã·Z©œš¬Ï^†±nS¸ÅbhÖ•쯾†òÞ‡f꫚k›ZÏžìÚö¬ò¤ç:–ªÙ*]ÏÏ{a,««–™ 2,ÇAìÄZ.~bnJ¤ÅÖ¥ ®ÚÒy\“V¡ËÊ+v6h):§^Eà¶-áþl¿Žá¨nâòÑzÎèâbѺgXn«AþãcÅ*÷´îà ®fâj>QäÜ (úÍ(El¬á)¨Ä«#†äÔ:«öb-Õ^­ÕÖKNIþ׿b}Ü ÛU¤J©emƒŽg¬§Á/Ûï–r_—ŠÛòêºÒhî¾HÇÎäQvÚ¼ÎêßVñÂîüR%¿nŒy*c¶,v†­k”Ī +)–%k™Þ5ª¥æ&jæJìOlÅÞ“Æ]•£ÞdEÔúZ"öåÓâäË&ëÒ/ c©Ê:Ëž¡ô¾ÜÕ¤ ·](–­ÍbŸ¹Vƒðb#¿n[ ¬†RùÁèR"¬¥›Â ¢îAõâ”êšÔ&+÷nï÷voÖ†ñ¶fâÞ´¬©šLçõoþl´*mN¦-&±ü*1­piÿ] óêËjÞvœ/¤Ý4¹ã.Ö\º0jþðã±¾.ðÅEíZžWZë¯0.|>Œªå6/jr([ž°òB1,b»V1¦­ãdÊjÈ ƒ óŽëÞ1.kÈ CíîcÞ6fL²1é…AÕ¤wU&¬*$sef#çrœ"/' mþ.s®*bÔ]²QÝK&™FX¡½fk‚±÷Žó“ó“©´žñy¢³0¼Ÿ03ÍžnÊñ.œ¢ÚÚñ-ç3pÙï3*àÁW˜º¸ò+"_:môù£ ›Îª3ã3xB²>©ób¦qž‚í;ƒÜ3éi·jj5«þrp)“ò厴IŸkìý§%ÝÎ{A¯‰Ó ªK þwk ¯®-×p3·í.Ã[;pâòò6 ²o´Ç»"r ä,5?D?µOB³×Å—Rpóúê×u½+V«õF-²ª±µ8—³YŸóÖŠ/Eo"z~-f´ÿÆoˆ\y8/¡9 ü2“>C5á¾müÆmdM³ºš+^òVsd¿yä¼"&H{§N;ò^—k]—Ìýržš¯a·¡ÁºÂv33êÛ§‹òI‡°ioî)wnºº±WÔWF6Z_–¢á´Ú<öC‡kORÌ¡q´®—´BiW_02WÖ«%_çv_snòêªuÞU÷î˜jõasÄAÚ ‡L8ƒtþÂfY“õ7÷:síZ·X'ZZfC@'vGŸ-3Øsï4n£l¹R(³4AÕ-g·\ãœ.Îô-ö/º¦c/wd;²D·óø’¢á6ÓzxU5_ß_š™w !6’ôi6ˆwðÌ? èŽeu·7,£8êR›ÈšÉÞ·ŒßnïG/¯ó„Þ®\XwêlÓ\ pðøb;‘¨ÎïŒÛ÷%%(²¢û¯§hƒ®o7t%Oø·,û^ Ä' Îg‚»ÃVzˆC¼‡£vJ«¶`Çž>66JÁwõ’û ¦z¢§û‚ç¶««&¬“ÀÆfÿpú>1þJŸÓ+‘7µC—<Î[¥°Øj3äs+âk \6[³ÁOïƒ58åµW;µ/½Ó/ß„ŠXz'©¶¯a­[5erü9a01üK^9¿3·ºË9»{©»t?‹© iµT¶0B=ð&2Cî ç¼:26ð&JoYõp­¶Çq†OnÃ×çÃcº¥gºÄ/¾\†ö‡è,º4¥†:­ צmƒ=É×½=<Ì•âú!¥j¨;>Ñ#5ã;Ðñ:?ß¼ç‡=ÒmúT{tGçtËóeµ‘²ÖÇYuw´7Jy¿µÓC}öªÝÔS++° £ýkò¶*|Ò}»yþçËþOöúýÊm“þÏA¹ ïpÇ»éêºSÇ[‚o¿ûçÝ¿/Ne¯üd—¹ G¾q¯¯šGúsL:ä >@@ "˜cy²kÚ¯ŠÒnÛ2>ç~ä oÄ]Q‡DO&Ô‹ôŒA•Ê‚5`:¥Ñ®rÞb²ùŒNG¿ÛðË­lNWÏ:ûŽC &†7¨å5X(†(˜HHu¨øÈhØ8)Y¹èy²¶&Ç·Õ9b’eUð·Ò ™ú§E– ëI·8ø¸–ç© ˜;e°§ÕÆÖc ‰‰Ly©|ÌœÙlü,M=<4w-­w•ŪùùóÔDŽð«Ѳ)†z÷½–þh—}O\{( ê?%§À~,ˆP`B^ 2|"A‡+N”x"•TZ¦1 CêÊÆVÐêÝB‘%Ý:Y#íݱçòT ˜ZšìY lI*k%{z¬æŒçÏe@‹=ÚL+sŸÂõªÒ ¸ˆMŸîZa@åJ4ý8±áÈ«*­°Êެ@=< } }4®Q·r‘¥;wGq|?žiÊÛq„u„E·5–LšàúŠ£ÓN_€úˆI rä¶$˜xæ¼YsæÎ G‡&-úsêÒ‡ ¯½Û1_T³íìâ2—2±,x~o·²6rÝ´|>…›¹íá°•ã]ž\ÙkH­ÏïþXfÇ(«âáÉ­Í;)Ë5ej¹Ø®îMå§m'sçÍçÛŽº~ºæ$kÃÄ)Yàb˜kÁtGVá‰ÖIc "œo&áÓVeÛI‡ÑBe”¡Fn¨áE zâ‡"žhbŠÆvá\ ¥%Ò0îV*Z…'ãC$Õh‹yÒõ ïxß~õå÷\’GI_2“áSS»@%`l¯qg]c8€·`±)‡chуYYJ¡V‹+6Y¤’l"¹¤›mÂÆâ“Óù—%åý'•vçܨ[âB]Ÿ­È#Õ“6) À$4­ÅZ¤«MŠZ¥§]jZ¦ªYª©¤œVœžóÍ•Ãþù(ˆ‚]zù "c}# ¦þ¨Jŵ5å›LΩ«œpöºät±—K[ØÁZÎ[Û"€*%u­NKyh1û—{–ÅÇk·¿z»ë·â.×ß¶ðm#[•þAJØcYŽ‚Øªe´z‹öRÅÛI®¶kk£Òb8b‡L0Š%Lb¬pÁ*N©f’/–âgÅ™tõ]¼òBhhŽÙ¸;­˜,ŠS´‡‹2¸¾†ËòÊütn”¡µB±7çyfp >›Xƒ‰þ4̽ÐöT'iθ¦Êq.ò¸.3-Ø^|:2qŒ!öd D“ÀóVûpSe²¦`!”^|ê)¦›ºÝv§þ”Â=·Ül× ª¹K:à¡?Ó*¼]{M’Ùš$¡¾HÝ´âÉJ7Ý2ÔNKβ°^) ¢yzŒù»Aÿ)¯€ Z-µ jfÑgi«Í¹òMùÓ±S.{\åNmßVþ|6çX î5Òar™3a ³…Hãì0 «Ø0ÃÏ;ß|ôÐOO"ÄËßUu²bHmLâ\‡.ú„î^K/ÂIdÉØ8ûãòÇOäò>ewêQQsñPbKÜhŒ|—k¬ð +k íLO8šŸp5»ÎÏ~¬]ȯã`sVÙWÖ¨E.‘OmÚ9\¡‡?vÇ_­[ÝîÃÊÐn3| oþhCÕ˜ÌXsÒݺt”;ÿ|fßA”¥‹WÏ.F»‹^GÁúY0ŠTœbI,÷ÂìXÌ"ˆ‡§/11“Úýî™kuŽ A †ÞTXEÚÉQ‚Rœ£µÌv.¥‹T7K ™!8"ž¡7Ÿ;žÎ~tÆ~í`Ò«öéÈH6r’דäÃêd1žt¯„™ô‹A'È2¸&‹@Ô ´Ä/æCH&ƒ¢íXG:Æ.JÑ›÷G¥sèoÌ¡ªBÉõ5‹cˆóÛ׸ÊFañˆ°œe›ùÊÙaòlTû ²5,ÜuÐFÀd•-¶yÁŽáñ~H[Ì\ˆÃ¸åPìÄ[;c˜þNwNj‡Šö(Bö@„¡DDÅ$L¢ðŒÃüœËgÊ2šuY&2“è?xuÑ;ËÊRâø)HƤO£ëQãYGB\.š$©Iïh®?ž°¥Biïf±³n–_õúä?S™Aã(¯“•¤$õ|j½Ÿöt¨B-jPµÇS¤lòL.è»´È>qTœ@i߈Ь24¡\]Ʊš?°ý¡?¤ŠêH¹¥vS*¦³ŽÖ@8‘]ݪVKªPæL3€³æDÓ‡3;y&í'R 2b¢0‘ž0笸ÏuÊ3²ï¬aeãIY±šï“JÒ]q }ýR¦Àã7CU±þ|¢¥ OÌk]ñúZY:ô¬ÅŠè9þªXUŽ©£Jx*T³©À±i‰·qÝBßc*‘ºö®'­ünGÍ ^³o¤„®JJÒzé&ÄNÛ@FEu_–4*$z^¢u½é=RU¶Tâ%éÙÕî—îÎõù„dW[s™»\» ˜¯Ky¨ÇßФ—|¢v·;~•Éxp•Ù.æ:WÂÀÎí°‘öÊØbrP{ŠîF©à[¨žO|çCÔ8 ãØzNÖ²3Æ,3‹ãÓžª•.K_"ã@˜²¾ö5 EqS‘ ‡µ%æ°“ü_»Î¶¸e…D­1Ý ÓP…íæŒº»bþR =§f7 壯Ðåkb EÖôø‘0hMUŠÛ8üÓÅÈ;âNÚ^ö–WÐèt ݼ÷")¾€ ÆÄøà".FÂQÕ¯G¬ÚJ5GyÍ›fÓWǦ¿N7u¤3p)‰LÚÖXhĵ0šÄëPjzÖN³¨ŒbÝËÃô` kŠj™^NlH|4U•LlzUÇ6n¶dsììË>{Çïãa^îYݦöi´¾˜õ¦äA4±Õp§iýdNz{®Î±Fo Ò‘†pw61»zƒeNîqÐmëtŸ(m±G­à”Òùk,èòZ“<Üz ÔP¹þ³%­^Dþzã7´Ç…fÄ–1šÄI¨"Ìj±¸tß­(qܧ€«»Ö3'×Áš·,º¥ öܶï¬b’Oݘ›¨L5Éšæ¸Ì èk(ýlÄö ì¯ÿôqòj÷µ´ÁÑ&Þ7*{ÚÑ®1ÙÏ.í´›½<Õ©û5³ú¤£(7¬Aõläp/ΉM¸ßkþw]M¹Ý7¿²÷NX·š9„j-²œÞ¢2Í›=ýÆŸ¹ŸŽy¦Ïºà9=ø…äÎòwõÞ®°ÐÇÌÅò éãeÇÍûñŽ¿ã°½¢EîW^Ó‹{­n|ªó z«ÛÒŒÀôû.¯ùä;=~Ÿ–÷™±Ýq[ôþÔu¤·\Ì{Ož&oæ—þÀë×9Õõˆã]۬ѷúDdù½‡Ýrd¯p쌀6Ú׎û«]ÿò¤'¢èôv»ÓcºöÜö{‡~FULd+äÖZÊ'~Xsƒ§EGôn‡§5Ã`“uºf©å~­†-üÆ(Èeyßáxõ×v/µR³dÖµp£ó ì:{vdšñXW~w´„'{CX{DH{·ç2#Wu¼Çe¾çe[—[¨zÒ÷rý¥,M—‚Y¸‚ädK9ó|XVZ–eß`€2Åjx÷V"è…zkJwPZˆ…[(s V~SwM^dugC$½UzfDiÿ²þ€&Æ1–OügˆÌv‡XvüׂOãY}ôf^$@HFRW(¨åIIÂd÷&‡‡²1GWx»†»‡%ø&6(/ð|‡¥YÛ×%(vÊå‰(؉ÎÄy‚õMç72X6¢E‰+±-ߦjSH`ŠˆÞg„BX„Í„±çŒ‚„q2rè7_Æ„Á¸÷ÕVÀåuqa|1W‹ã¨‚)Ó|´•4“`øD…媈gXFèo#¨H±ö†·‡¶8Rt˜5vˆ[¨x_å'ð¨uRˆSÓ—}®“lbg.û‡ˆ¹ˆ™én·s18¨CzFSB+EG|§¸JØwúˆ’Ÿþ¸\¸†×Tç3$YS4¡Šy؇x’g`$èF¿F‹åÈAÉ|¨R_g9ÒEIwN˜Q_b!tÆXqaе´ŒÐøŒ³ÇŒYI„ÓèJˆ3X/`Ðâ‡u“zW+U˜iä¸n 5Vù?^ˆK|‰…-Ài¦µj©gt„džI'<ù¨’pY˜F~ÿˆ'wˆ“Q·xóV“,ÁŠ0%|ž!«Gˆ—A‘Š˜ˆ›é™O¸7`Ø‹Ú6‰Ý¦€Äh‰Ø›È@B ”† .,‰L˜ˆD:’/î)“®y…°¹ ‡9E´I[¶IŠÓŽõÜô{®ˆ–_V¯y\³(Ÿõ©£ Êé‚F ƒw‰ Ji-e)ŒÞÕ—y¦_SÉBÛ#—\ây•݉¦—rI˜{¥˜Œ=1£di¡xæ}„T¨D+‰Ç–LJþ£Pê¤Ïus=- ÒœôôP¾ä¢Áä?ªAO ‹½Ð}®GŸ9Ú§ôá R¡ð3BÚ:Ý8§á1U¿‰VŠ™TIBY‘!šª$ºª%ÚÕd>¶Ž“¶ñHfzñ–€ô¨–Åwœø¤ÁZ©E£Åå£T7£k¹eÊ ¥ê ¡ì¹#IúQ²è“MJ©“ê§IA”3H¥U²ŸW:ƒE 9H¬)X¬÷¦Üy¦íZ¦iú®îš={…{Ę¢Æ„4IZŒÁ¨öìŸmù§Ø*¬šyŸèx`ü3«q'†x矉jž Q©†7z n˜ Ùª±{:¤˜–¬*7¡ÆFXŸþêÅæfÜÚk—‰‹ÂB§ YŸÉªœéª4ÛªÑw¢¦Ÿ¨³öP†7¸§å” È€lh’À:¬›´ŽÙ±µi[!Š™fÈC†sW J:œ¨ª´]û§RÚ`€U¨|ª‹¹u«)çŽRÕ¨D›‡1ãƒWžðJ¦s·òêjU9Õ¸©w±›.ú71ú4Ø«§°|êµ×:°ê’‚:3¦.ìØ°V€~; º:Ü%­è©ìš¸ˆë¹{“˜ ²÷•éwuÎà·ÏʶﷶÖ¡Úªª6+»2[³4&š–º³ã1€ÁUƒ&K8§Àq4Ê}¿úš‡»±K[¬2s¬¤»„þ2)D.Ѭ»¡ú¢º{V[Ë-È˱Ÿ;¤)Ä­p¶°Z’”*+D?»1û”µE±˜ ‰·vk¦ñJ¿t;¿¸²¦Ôئ@ª$K¤)'\–«”×YU…+Ž›¼Ü[~ßÛ9ù™‘Vª¬Yvšk´]zwYk±É† Kë½L'¡‹©£¦8¡í+§‰Zµ§vµÃ׺*ôºö9³´{³³» «ÿgO)г£—¸º¨ÖÛº-¤6j­ ŒÀÝ[‡ÀÕ£OKºÖ˜cˆbûº‹ œüoKZ­¹âÁHÌÅ.%ˆž7¾Y¶Xl½©ƒ(qÆ(zá¦Ie¿r[·õÇdJžMe¯#|þž™˜1‰ª¨]­O9’«ÃJ†{Ä[lÈ §€¢èÀŸÇ1ŒË[>ËÇÀ[S!¹«fa›+—¬Àpy©›š©(¡‚¸²Q\¤iI¡…¥ú²‹³5ìÊ1üʵ+7·ÛC:¬%+ªGf1½êÀVë+Éœµ»áu´Ç[È›lœË FLŒÇ¨ì´µË6‰IÕ ˆ:‰°.k‚ÄyÈŬÍsùb‘¨ŽÞʳE€¥¼—àv‰C«Ç銌ñ+Ç÷;ÇïìÎåUǵº¿iTž½ÇǦ7ªvŠIx:P^Žƒ•±]lÌivŽŠ,jc»Y‡J}¾«u˜Ëu|‰½Z|±ƒ9ÐÙ¬ÉõÙÉw"š*,¡~ŸþóÌëÐb€¼ÏJÆ¡¦ÊÊ-;Ã2Lð Ójw‘‘}©T †¾†% |}ƒ›%DLÑÛlÄÌŠge?ª'¨¨[z},‰SlÅû†ÚËÒ=Ô ¶E)¾à¬»Ñ¢RC6Ò+‘†&,;ˆ=H•b Çñ¼Öm-¿>5Ï<|ǼÊ7Ý„ù,9qé ü%° ØWý¾—«:‹<¾p°¢yy¾xÍ˾3՗܆Ñ‚]ÙÝWsí¦Ìœ²d£,Œ×g¹ö¬zéúÂèÓ-˪ڙEË(úÀ”éÍ]z¶Mz†ôÇwÔ„YÙ}Ì¡øÄÍ»ÌÛ#µ{ÜÔƒ$¸”i¤þ&œÔz°¼mÕ¾mÐÛ:Û û¸Ù®¿øsÇmýªk««ÎÚ¹®c ÏnÝÎæýÆÌ”¿_YÏòÅ·ë Úi¸ù%ÄËÐ{(ÔÒ¼Mx†}ÝÎÙ’dÖ'‹–? Vú˜,4úÍà}ŠÙÕ¤ÙÚÑd¹vQm}çÜh|6¡. à¨úÒ²ÜÚ.-âéxÃÉȵÌüÜ‘Üí%š«+½»ãÖ8ݽ=AE •G “"ËÐXÇâÈ­šÙòÅÏMãùmã •ÕáK…:<âl¾ºlá†Å8¨w`ºäÍÖoÍåçÝåø ¤ìáxèhcY¡ñ ÒlÊÄ‹0'ÐIŽäµ˜É<þVþÍG¬§DÎ?^>î—CþÓ“AGØ þZNHP;˜9µ|îMýyJ3ØÍ pÚcâ—ÎÚ˜þág6J)Μa¼Ðv=ÁŽ®¨¼rû±Û„nÙ5>.8^[:ÞÄ{[|æ¤.J& |%TͬçN·äÕKpǤ.8Ú9]zgàÿzŒâÍÎéíåÑíÓ>=qÍ{cžƒ<œž¶îÔ&·¬±ê üæ¾^è˜Çß·”ÐUÚÈü©ÜËíÁ¼7@çþj‚9èp^îœ ÂžÜÑ Ìã}ÊeÌÝzýïǶ½•îá#⫽é6;ÓŽhˈ­³-úîUžwjœç/7ãø¾ê‰þëêUæ”P[HÌKØãÃíG …Á©µÎmf?™ï¿¾Á.«\-ÛÙMÛ?ð+G_<˜5o+–[.íåýåB_™ðÕÞ\§í©8åœÜý,é}]’ñÔ/Oõr8ç8g¢U§ÐfÞã{Îí£\Œ*ÿP ÎL†ó(‰èz~²^ÂžŠæÛ¸Ôýɲ®«Ò;È ¯ðšž÷7ûÚ:Ë‹´*×ï¸ôÀTÉ=ñŽêoöÈùñÒx®ÔøÆ¬ƒ¶yš¹€ÉëpTõ‹oõÔ=ów¾î6¯Â^òÂ+’©4Ø>ÏDOí@ßúæmíštô:—¯ƒðöp¿×õ}iâŽß›¯øæ.Æýîÿ}Ë‘ë¨þ8ÏÝm5Ö€.W‚NWgÏùq˜ö"æ¼Røu£Äx·ÏË¢òsïÂu/cxÏð{/þ¬úð£Û‚+ì§ŽìÇ­ó¹=2 ¸ñäÞñ)ØøîæŸÃù[Öèßôg (ˆcgZQ(Šq¶-Øè‰ï¹èóh½¡°x3þˆÇed>›P U)½F³UgMí&sÛ] `veM>’øé³­Ñ½n¿ãóú=Ž[½Ý´ùÀ(@iݬ´,ê$5B*J>NòDRbZV2n:jfr‚z†~–’žŽ¦^–¬ Ža ¶Ì˜ NYµ.ÍÌñùþþî´9 2½:Â,̰Fé"C[%rIGS_þãbÃVskOã¶ ; “çè–Тó7{ º‰ô×ÛÓ±¿‡]µö“ë—‰‘O ©mÞ¬eKhPá·…BDøPbšs„àýá1ë ‘s."ÊBïI>ȸ» £%C¶¨™{¦YÌš4oªÁ©ÃfΞ;uÎôô§P™FyM:téQ F½¬dˆ Ý™âN|‡WÉ®{l\ýy«]ÄÊJ¥Ìz°›T¶jÛ® wîÛ[X<™ÐWÓÆZÿPÑuµW¯†í4!›  à†˜ícùÌmY¹o/W¦›3ÅÎã¢b*"ÝŒ•€†ZwuÞáÖÎ¥ ö Ë‚.ïŽAµJw§Ýþªzå{xpS¿…ç nÊ+û’YW7)Þ#]—Ü׆YÅU^(X•¹g˛ϗלž³óö #çM«e™ªxSøÁÒ8º—ÂØ»®#lþÈ7:ÙêµgÞzè5È ƒÞeQm uwüÁ7V|Oø÷IyÅ1j½—Âm,%‚S.6UŒ3:E£Œ5âx£ŽóÙÈc´ÍvUµ”†ÒP›å×k"–”$mfäD+gô!„b)¡–ìeÉeB ³_J{é !ègx^èÄêöd¡Ú5¢›oþÞ"Ž“Ý]Xˆ@Í¡œqÄ-·irÇyÚ©¦£‚J*§¡¢jeëeXŸ_EX¨ ”òX÷è='Ñ7›wŽ…uzþ¬ ] Ka±k…Cèã©:š}ƒÉ¹,‰E,i+0`1S¤Œ¥‰—K`V¨±ÃúI®¸ÄRT]<賓‘«dÀ&Ej´Ñ[B›Öꑘ¡Ç x¡+Â×bŽ>îøâÀ#Á #̰ Cüp9Êòyh‘gÆÆšrà ÌšúâE©6Tª ¬¹Ç–;®Ê讼¸ÝŠI& f†¤ß_]VkǾ0Ši‰3§b ¾zËG§Œô¹I3hóîû®UZIqâv¸V»³þ³f¥¼ šu骕Zö©¦~z¶Ùi³-êÚn¯¢*1¬º›Î†b+ß½Z×1­|š\]ï6à‰§Su'#ÞòÒ‹£Ì»Ûý¤¥A]`pòÃ1ß[·Ë✑#ñíØ]7^zâJ›®¸±††aÝa|óºÌIáèæ}§È>0V'ÜcÄÂKL¼ñüñ 3ÛõƒW­»°÷æ¿KÚ¹ö6¸ZVžÎ4ãá¯zn£ƒ>fÈe¾Û‡ÒFÏæíùò›+·ðkôÅX™l¾ÿ¨“/u,sÅ V3ÊA‹€¼sÇVt6¿;|È&ÒÓÞ¼,uL¹ìm¨BÜÚ¶A rðƒjþaqäö¾Ë´Ên´£Ë¤J`»A1^\„V8Ÿîâà˜¸d±ˆNóA åL“1+}LIÖ»¼Ž7 !1M¢›[¸xX>êðŠ;T×{ìòœöEmv¼;’.–È·|dÛ« "|7Aø Oyr Þ¶<;Ö1ŽÌ3Ü…ä,"ÝGéÇ ç—¨*®Ñ-$óH­èH6’\/K_|d†:ñ„Õ¹JX y»bÐgŸÃŸÐîÄ¢ÓD2•X\eU¦@Þ¥Q:E4Ò ¨Æ dí}H$×ê5¯)‰Š™!1IØÁcŠÐƒ!\f1«Èº-¥v=³LE`Æaî»+þ á|EFU¶’•Z'„­(mrö’bè$JxòŒ‹ÌÏIž°b’U‚¤8 NrN…ulìÍšÀHXî+ñÔ®hY?„æÅ4DåõˆG:bô¢µ(G“W”æ¡åyDC©Ù¹\>ð‰My㮲È&ö“Ÿáœ)@Ù2IR†‹/`üܹ=ê·”Î9 $Y‚J]*S›êÔ§B5ªR*U«jÕ«b5«ZÝ*W©Ê@)äÖBw–Äüèj˜ì‚AWÛêÖ·Â5®r+]·úÕWÕ,3œÈÙ5;6Man*¢¾z×–°ˆ]lbËØÇ:6²¬þd+KÙËZ6³˜Ý¬f;ËÙÏz6´‰5ÃhI»XÓ6²ªEìhIJµxP²~(_/«ÅMJµŒmlhAëÛÞ÷·Â .q‡kÜâ®–·U®gO[Úº>õ}Å—ßLx"~uцˆw»ëÝï‚7¼â/yËkÞó¢7½ê]/{ÛëÞ÷Â7¾â­Å̦k­z.‘#ãîbÐßðø7Àð ,`øÀ N0ƒìà?¸Áž°„+á SÃÎ0‡7ìa ÿÀ!æ/z#²’þ‹œä ;YÉ3ž2©le)W9ËSsºìe.{9Ìb–1™Á\æ.K­zAíÛ<ØJ¹Ðw¾R}êlç;ã9ÏzÞ3Ÿûìç?ºÎsvq·È0h<Ï9Ð{¶[Yý:ÃO”gÙ1š™A‚WÌ1Îô—ÉÖ!Ø­´äˆàW =UJÌÂR$J ­HÓWò™@Tb‘%}„¥ÂeZâY À®¡¥[öÛZBÆ T¥=TSð9›×üÔd(Û`ba:aÎßA†}äÅÑášÑ5fd:‚cRæˆ  æÃ]ÙfjYg΀bî€/BædJæhš¦a"&  ·™a&jæ½¹ælægJ%W"@^¾É_QN#6þ(Txå»'¿1ÃTÚe}ȃlj\É1§ÃõŠYD]¹'uZ'Qbgu®%ŒIÉ…s†[u–[ÂYÜ\Š'¶'ÄM%º¡§ m'Jè¦/$F~O‹%d":‹¯égu¢Ù~RY–f~>çÈ5çwŽœY^ ¥gv^炞'‚ìÀ¨sè~ZgbÞf¹1æyþgzZ‚h½y(„öPE^ñ¡¨uÞöfL<{'º½[rªÞÊ™›Ê¥\ºåhŽÀZæ§q~[Œgt¾·ñèÄé(ÓÅ[¶½§<Ô¨B.)v®[”NéZÞBùY¡›ùæF6”IçzN©*[ѨrzSß™ÞþÙ©© ð,Ô‡cÒJpÊé¶Í©;€ØHçJ*Aš^áÆX™&»ˆ˜@†Û©\”NYÂñ乤ýŸ4Ê"¡a^~6€4@¥n±…¢!’C+(j‚²Â¥Zj4 \j"®ÝM¬Àª– ø¨rVj¬Šj<@©úé9D'dž¥Zê¥újJÌ«æ„6Ã©Š€•ÆÙ«€¨–ª­NŒä±*þ¡‚·…e(däaz¡£¡ÄF”€HCO Ü1‚@ìdÌ@¥žÀ¨Š€¸Rb¼Î_\¦r¾ë4þ9«Ûœ«ìA¢ºÞk»þ×H‡¹ž€­À§æ…3²k¸63 ßJþ‰ìݧ¶£’QÕV¥\$‰}”*ѽ ÝÀ¾~*Jú…³2ƒ³†ìþxë×\NÈþšÀ«¡‰«é=€¡(¬<ž¸§³²‹Yƒ0CXúÀ ¤ì¹ÁkˆÒ¾šÝ5˜ìOF–F0rÒžŸVÂÞVŠå«@-Ü9ëfh$ŸÍÞÐ’ê=i ®žÚkÛn[©E í@Øêï5)Ú,Ýî+§öfÔĺZ¦÷ÀÙ¬½Aíñ‰@©n_1B.›æ½Ä'ŒŽ)æ•Á-J|؇Ñâ@­’ê©®l¯>®é’ª¸Æjêë§‚+èÆÇÊŽnÞ®îéÎîÁ²«±Æª¸þ¶y‚ê €.dت¬–Ëòêé6¬¯Þ¬¢*ÔϺۦîãŠî©Öîã6¬L¯»Z¯ê–@µfZª,Ž®»æ®±¦î¨æ®öV/ëm¥º«Ü&íåBÐÝÝ\–àB ÅFÈn¸Â+ù†kô€» 0ðºçª­ ©m³ì»>¬C07¬Û­ÜJ(Ý*0û¯P0¯kÿB®&3ð*ÔëÍ.°ÿ2°ÃFpò¯ÅÊe-@/^L°­R0ì« ÛpÈÞ0'¬Œ©›Êï<ÝìäaV 'Ú+ÇÂðóæ0®µï¹µl"®“Êð¶- '¼@nñºÀ¾Újþ®þ(oY©B/è«·±ãð±Vnœy`ƒî ðêŒ9qn?ï£ÁòR-Ó-ѰðÇ1(ð»–0ÐZðßBm‹r ?îóÚìêr°Œýòñ&ì'CÔ½±·±².2/ßëþ¾2©ÊX›~®æò#ï/ô¶l4/­8ó2ûq*@%bì=@*´ò"^â¢8/ÞÒJËÎrøŽ1u²2‘j‘ܬ;Ïs,7l!Wñ6Û,Û6ò±ŠRÕñó@îr6ãë'Óþ Òæi/ë1‡ò>ïÃnðªl2²8'š½Þ±<<²"û0 ¿3¾¢pÓ[ËšíüQ²W`„æ–¢ëqmþöò'31«1ìŽôÁ>nKÿ«¯À?·kpIK4Ut+åÜB- ô»/Ë^ôùÆrÏât05Ýj/ùro?ñÊVµ˘ºiUh/B[jU#5B?°3µ0ïp <@—*\_9ߊ£6Ÿµ>ÿ(Á¸/õ‚µ»/E»pHÛ®8$ 1p?Ÿïï°¸¶õ/#¯3(÷stð/+oÐb6Vsðñoo6DÛaóîNö 3±û–.b³îéíñþ6,DGôºÎª›vb×¶í®¯Ôªeóð¯R´Hò·1ekì ßý")€«’Nå¡Ji¾ߥ+qŠ'ÆÉ¨¯ô³».\½¶¥É]'Qòg¾õìž\z;q’‚w”Þ©1§5dk÷·áèºÅezé8c2_÷µ"b%×&1[Ô(§ùw‡ÎÑþ¤Ò†g„{æÆÅÛ^5»õ×ÅT½ñ(‡/8ê6¸j\¼å²‡ËwÈyt$8¸f’^w¼y(È¡ l¼´a U¢ªôù%ØÜô›žø¸a·Œ¢êkŒ¾}kº²ºÍÌ-ç7ÑɨøªÛqž,U˜Ü¡q¶žJ©ÈêC1 ÁV[âþë}ô‘ÓGµÅ€ÑñE ýfV\Mw¾ƒ°bÂhB‰B¸&Ým|¡Š›.Èìׂw‰°jžë¼*Êì³Æî ‰ÉUè¶•Û)&ÎÖýÎÆÌéɱK77,]ýªBÞS_°Ûee0fKÏŽ:¢‹à›8üð´¥L×àáµ5õ÷Ô¹%‹o,A}¹½öªx°Ç Jü¹$øˆðæX­ùLó¡¼èË>¡Ú÷.qó ß´ËÑì@•?Ë m‡ýõº Èí='ú¦ ÖÏ£»÷ýˆ;ŠŠí>ÕgýÏ~¹£¤ÎGýá?>Ô ~××áäæ'ñT|åU|íøŒ[–¹V°MM¯±f–™~–Afë'ÙÆšþ™göX”åX'¹¾‘‰¾zsÙ’Á>Ñ~¥_Y‘õþ“1ëûZí§ÅØço+ÇÖ+Œ¹âE¹Ÿ”úYõÚ¸~üW’: y¼C>÷3¤ù÷YÒf¾æÓgNãÁ1K°Š`_~ajjæL͉ҤÊÿè !±ˆcœb%K¶k¬Æ±[Ã"‹ž±qç²€O§;±lÇ YRÍx¤h0I"þnV“ ÈmâL;ÒB.›Ïè´ú\ÔòÀ[°ü%¯¿žïüü݆æézt€~;z†„ˆ†ƒ}Š4މ‡…’oƒ˜Ž@—•”žšžŠm>ck§¨§ŸR‘“F|°±­U&€‚€}¬þtm3w<:»„¬a…¯´µ”Ç6~ÇÄ–¾Æv¸Ô0Ã…Á‹yÛË·ËáÏá¬ÞRàB¦©ë첲呿¿ºŸm½‡ô®rú–ò®X§ ­~÷¡»ç…Áƒ¼<ØÍK±j)Z”È1 êÚ‰TóÄI+q{fí“öhÞ»V}þ}JBÐ2—À*ÞŠøÒfK77úœ˜óePžE­äf(æM§õÔé1äÈ«fNîiÔ2_EŽ\½ ,jïâÑ—&R+SmPf`ðÀm„Î-ÐhãÈ ä7©žçìêíäæä´ºÄÜÚÞ4:<œ¦´¼ÂÌ´Âà$:a¤¶ä¤²Ô¤¶ÜŒš¸¼ÆÔTz¹Tv»\z¼\v¼d~¼”ž¬„ޤ|†œ,:^<^ˆt†ÄTr´4Rt–Í\v´4Fh„šÂ4Jt|šË4Nt|–ļ¾¼ôúülŠÁ\r§4VŒ|ŽÆTv¤\r¶dLj´d‚¼Tn»,J|tŽÌLf´,>lDf¬tŽÃ,BlTn™\v¤d‚´Lj«4NLf¬4Ftôöù\j„dr”ìîüTn¬Tj¤Db¥Lb¬ÌÒÜþ `ƒ*\Ȱ¡Ã‡#JœH±¢Å‹3j$ð¯£Ç PÀÀ(O¦D‰@eK” ,Isƒ›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H‡‚\ÚQ 8˜JµªÕª @€ B ŠK¶¬Ù³hÓª]˶­Û·pãÊuËäH RT°°·/ß¿{YJ½€! 6pè ÕÇ­@<Þ*2ˆ–1o12gÏ·~ aiÓß4I½z«jÈ;ZCØ‘ví­´a³Œä6$»·"1Á›øVVÆ!´JÞJäæM%‰>}«têÑ¥@v¥}+÷íÝ!þ|÷¾G)È^ÎoMþ|Ý$ HEP¡„ýûøñW˜*5‰œ€B *¬  -¸ à .C ~   1H¨`…z’G†*øI‡.|8¡ˆ ‚2„¡¢Š ¦¸"Š)LXH \(8£Œ1Ú˜…Œ;*È þX£ ‡ð0d‘’Á„ŽÈÁ¤“ Ò¥ RNXKVNy¥•X*¸¥—]º@ˆÆ2A™g*hæ„ïuD€ RYP 3Ð0C wÚPƒžzÞ€ƒQ9€9è°=è>(ÚÃ@ôã#LÚCBLšÃBHz)š2ª¤¢dᩦNŠê©©ö°ê¤þ_´ú… žÎÚí¶Nº­’î*iTrk¨;i±šî0Ч;$ÁlžÚ"E´ÓNºÊ´’"1Á­9hË-¥xºJ¸’îAnær›î¤·Âm+îNŠFžb9( ššA¿ÿJêo›äU_4PàaD GÜàç~ýéÐI(±DL4±ñATzkÈš†Ì­N BÊ®²ì„Ë ªs±Ö*«©¸âœÃˆöÊk¾Jú† š¾Q‰¦©ÈQ´°’î tÓI$ëlÓÕö° ´ÖbmuµÝN ©·å†Ë®Øè’ÝŠØ=À›ÃÚjËoÚ€DÑC¦Hàé¾së þ·¾G@ ç§¿¹-è¯ß>¶hð90òo~‹äX, úK`Aÿü9øÜ-h¿º,*õaØfƒ#Ø€ 7€pPù$ ]˜‚h–‚%€sÀ‚¼ …&Œp %¡P¦Â0¡…)€a ³ BÐp„6¬á ½à¨°‡þ*äYMD9¨pF!¾!‰^xCG(E¦B *ÜG¸ƒ dÑ‹\£º¨B[äB…«Õ8Â4ªlôßè¶¢vÄ£ÀЊìQŽzôB+  BSh 0 TP1,l dØ‚k@H¡ sã Ð3Dá <ÃÐpºQ‚!Y@N™4¤ Pà*ÑpYª²–³T].å°Ë^ªò¼Teâ0Ëa“˜ÂìB1•©JRL`–Nx¦*£ Mi¢Á º€f6§Y~¡›ª<8Ñð Ìò.8g:U‰Šu¢˜%<åOU¦B³þ¼ç,wPO4Øb ³ü§*áO, aS0¨?s0K`D¡¡ESH1`G¨$Œ°2!‚e¨ÕŸiÑ kHèRš!ln Z`RÚÔîs75ê†Ð:,¡§<ý\í„j;änsFý\R‘zÔåIás_x*ò¤:½.@•ª_˜€ó´º=®baÚ_ø6ˆÏ‘õs((ëæpÑÏí ­›ÛÁûäêÖ÷!á}«ÐÁüôjP`$ ,þ·9`ô`s›pC#à A$b)kI}¨§Hzt ­(˜—¬í IøàH—Ò5@a¥k¸fŠ…°a °½þ‚ `›ÚÙÆÖ¶0•mµ [Øò–¶?Hp… Û t¶ÆE®”K[&”‚¶Tx.l£ ]鮺Ó@u¡ Ú¢âÐïtÅ{]Ðvæ…-*Tà] x×ï/lQßùÖw ¸¸o0”@ÛüÒ6ú]mí£†”‹€ì|¸'#Ü@£G(Ã% *K@ADˆÀŽ¥B(­ˆ€šÊÔt'^ÃR¼â—u¦/^CŒƒ×x¦¢¸q‡›ºÔoÃS½ª‘gUäyõ ºÀW×ð]ïaO­âSëPð€—â¢Ê›C\±@׸ÎÕ®`þBÅ\Pÿ•yg& þöð1\ ›ps@ò·©È‰²‰{pâBê†l–¤€ äðI,Ì!¦lé*ÑÐ!¬ %,yðJ4Ð! •®¦[JsÚ¯ÄB@ýi0˜ t0)ƒW¢Á˜ÂDæ«¥PLk:³š¸ž¦5 hæB¡_(ë*³ºè ´U•ÆVè\`PCâ•`@E¯_9OvâÓÚù¼6ô©ÊhÛø4¨-ÌÐìq—›Ü€µCU¹Š” ÂØÁ»…aŠ|¤`'I ޏ=×@Âp¸ÔPÁ¨øG f°ÃØp‡%ô`èÃÛÀ‡/¡ óÂ<0‹ƒ€ïAþî’œ 9Ê6øå.w¸(ˆ`qà¬"ù­D€òÿlhÃú­„ÞƒüÌiÃBúS‘„o ÷ÖOÚ/H½(èBÔÃåp «^VØoÅŠ¯—}X¬p×­LႪÃÍíðÚ Ø÷ ËXÂ&0 %¼{{x·G"«—Ø 3‚.Yƒ€œ³S¹ÀV <ð` 9˜€€yÍû` QÐ|2Ÿƒ9dJ¥Bç_†ú)8Á­wBV?ûÌ ŸÂ„ú(¼zý)R…â£" QÈAPÀå/ÿhÅOE%ŠéSßúÑ'tô%þq}î'?£èý."z[Ä!ùQX…×’o‹.  ƒÈêyÑÔëa þ*ò_üýë?nÅGÔ‡ü­ Ê—Ä7ʇ€Ä ø/ÅG „bs2 90o xn²`%pão!åx÷'ö°Y` p|ð‚ /TÐ.h_À‡a¯a€BPƒà‚Ex„A¸@ˆLN˜ƒÀQƒ(  .øª ‡± Up° Yx{ ¬ ­àgø¾a hÈ9h £Pƒ·`.(?Ρ…h`Z(?Óá‚k 9ˆá±Õ„þ‡¸wPˆwè…` {艒x”è…ìá‚!( v°w ð‰|ç&UQ8pŠ8 ©¸Šª¨Š¦HYáð€ðÀµ(ÐŒ¡‹‚@‹¿µø;Œð€Œ˜A‹(ÐŒ€# €€P†ØX@઀ÑXZñ{ÀåxŽ\!ÁñÐŽ{`æ(ñk`*°& Ž®À´øµ`ŒÑK åX)Û¸<ØØI0‰hˆ…8‘Y‰[±ù^ ZÑŒP޹޿A’ç!`¥ ð~ Ãðþ sö°Š§X:Ù<É:yŠ­~À]0R@>EY- ”ƒP†P”p0E‰!`•ƒP”qP‰à•¬ƒ0–e¹•¯P”]p#`”jÉ–°  qP–Žƒ`–„0fÀ—uIMz ˜ƒ † @˜‡ ˜q D@˜q@|P—qpMP–Ð l`™™—ƒÐ ‘™—½lÉ™Zé <ÐuyI˜'’É<0›²I˜´9›µ ›<š\}Y À™— šÂY–]P „™ É)¬9\ ¹6©Ö¹j°8þ Ù¹Üù©øÖ™)Œp™diž„Ðpé F ì Ÿ‘ u) ŽÐ  -0 F †ŸR  J‚`”qàŸç9[ –y³Ð [ü)wŒ0ª¡ðé¯@ wŠ¡#°¡]p#Rà$*àÀ0ê¢RP—¾0˜eé+Z—\К£,*¤u Y–*™uù |00*Àb¡&0¥UTŒ¥°¥R £`0J&bÊ¡.P :€P –éP–R • V)§qp£6¹zº§|Ú§‹@ Ú§þr0 r s œ ŠÊ¨q°¨ê¨Šú¨’:©r©˜j©”º©ú©Šš© ú¨—Zª¥:ªŠjªªºª«j —*©¨ú¨•À©¬z©± ©š©ºZ«¼Ú«¾ºª¨:«£:«¢ª¨` —€¬Êj Ëš¬ËŠ Êz ™ P­×j­Øº­×š­Þº­Úª­Ý*®Ü®ß:®æš®âÚ­ãú­äzÖÊ®ñ:¯ðŠ®í ®÷º®ôª®îz¯þú®û¯õ*¯K®›®çª pQùѰ››`[[±{±k±{±Û±˱ ²ë±k±$‹±ø1²!«±+ þ²%û²"ë²*ë±û°6Û°$ë± »³<»³ Û³?û³ û³pQ [œ´J»´LÛ´Nû´PµR;µT[µV{µX›µZ»µK[?Û ¶ ¶a[¶ ´@¶ K «°H‹µ°´q›´s[·t{·œ0·y‹·v»·}û·|¸{;¸€«´zk¸‚[¸‰»¸„‹¸û¸ƒ ¹\+¹öq´7Û°C{¶;+¶Eû³o«  º¢« `[ºeÛ¶š‹ºª›ºš+¶¬«º«»¯;»²[»i˺¦k»«{»ºK»¸ë»«ëº û»¦[¼·k¼¹ûº÷±°4» ÎÛ¼Ë ¾{¶{¶Ÿþ۳؛¹<´›Û³j›½Þ ¾B+´ß{»<[¾å‹¶æ«½ê»½@ë³ð¿ëk¶à+¿í+¾õ›¿ú«¹k¹ûI{¿šË¶;û¶=K ‹Àì{¶»«¶c ¿ÆûÀÌÀ\Á|Á¼½Á ¿¨ûº¢›ºÃ«»_›Á™›»m°˻ |™ËÂ(LÁ/ŒÂ¡k¹ï•[¶d›Ã· ¬¶ÕkÃy«°Œ3Àû˽㫹ØK´-ì¾™{CûÃ̺Qüà ܾIl­ÿ‹¿TÜÅh« PÌÅ_¿¼ÅKÜ¿6\ÃDÆ;ÀF̳Cœ¹¼³E[´á+»J,¿M̽uÌÁ<;þP\½v¬¾X¼¶IœÇ~¬½ELÀ€ÜÁ½‹È<Æk»ÇìÄJœÄ½k»™;±þ‹ºѺ;,½j‹Àdk“JŒ´àÉ#1BlÆd˽‘Å#Èܶƒ\ɰŒÄJ ÈÚ{¾ô ܃lÇÀŒ½ÁÌMl¶º|¶¼|¿`Ìʾ¾f\¿j+±i±Û‹hëÆÙK 6ÙÊsÜÌÄlĤ\ÌÆ Ç;«À¼°¼|Q䋽E[Ä kÅoŒÌOü³\ÎÅܽäLÇB;ß«ÏûÜÏüŒÎðŒÏÇËÎÑlÄ£|»åüÐÑÌÉi̺Ÿ|ÂÌ4]ÒDËÇcþÆ„ŽÙ5¬Ýœ Á.Сýß[æP¬àÞÖ‘~Ñn­ã=Þà:È•®Äuœ×~Õ nÝ„ÎÙhýɮ͛^ÓnÔF›á®à”þél,éœþÜ­â…ŽÝMþnêëº ›·Æ<åvŒÀoKÒˌȿ¾À~\Ⱥ>ƨ‹ì¯~»kþÎ]¼æó›Ë%|ÅÜ®ËÂ˺Ȭ ÒÞÅÓ;ÁÜkÝ«Kê@nÃØÜÕ‘¶ŸM¶ÈìÍŽîÆŽ¬¹kN¶Eü½ [íãn´®ÛÇ»œí½ŒïdŒÈÒþßNÒ ÿǬkÜÙú>ãókñy^íT ímî×nÛëX=à3ÀÍMþÖG·„ÜìÉ<¼^|É÷à»ë‰ŒÇ \Áÿ¾”, ÌÂ+ Ã,ñï+ó;󗌿,?ì<+±`›Ù¾+Ï‹~Ùôžº<Å|È/Éñœ¾Ÿ¿IÌÊEö÷^ô]oÉeÜÂÐ ÍÀ^öelõlÏLMèØÝîöQµQ®Õ%>Úœp¹|ß÷~ÿ÷€ø‚?ø„_ø†ß÷t¸q»ø~ëÆŒÇm‹´‡?ù!KùO³.kùùΫùž²$üÈ Mßk²1Ûù¨Ïù§Ï±Ï‹ú«¯ú÷¡ú²Ïú¯O±­û®ß¼¶ÿ¼¶ßû©ïû§ÿûÂß±Äïûœ_üÇü˜ïëy\¾þ/ïè\½g?ÍÔ_ýÖýØŸýÚ¿ýÜÏì§ÛÁK>¿ôÝòån¶:l¾:»!qþìoþî›Éîþ³‹¼*Üþ -ÿøoÿúÿûŸÿüÿÿ S€š4$xð`A„ Rrø0†d¸P#Ä9näø1À?’%I.¼èä@…*]¢ 3dD.CÊ™3¦Í:yþÌ™2¤E¡@„Hp R„P*¥ RhÏ-M^-‰±¥Ï™5½¶¬êlÆŽTË5Ë5íZ´e¥:$z”¦Ü¹&•¸µ¡Þ§]ûĸ¤XÂ{gÆíZ4åAÁÿ¾ÆÉU±ß“û^®ì•ãÀ¥ ã2þ¥K·ó?§ñ6„Ø!bÖ«•6†í¸µÇÙr-Þ†š»SìÆp#¢D±vnמ}G^\¹æˆ§?7wHš¡s¹§—«ú4ïØÙñZü®}®õ¤ÜÍ»ÆK½3vö¡Û‡‡^>Ôðà«K$zšº~À¤ûZG()þP3­!ó¸ :%ºµ4i9 \0Á ´0C 7 ­Cä°C’ìê0)ļÐÃÝ <¯Á5d1F¬ˆk¢ØÈ£PCqL‘:÷Ž‹±´ä .;ü¤DÆ1djE%Ÿ„ÍȇXÌOÊÔˆÄòHü®zÎC‰ð’‘ĸ°“/½¡D3M5×DGqìN8)‚CRHíS0C6÷ä³O?ûÍ85§ë‘Áýúû3QEe4J¤ú<ÎÅ Ëk´RK/ÅtMi)SO?5Ô£µTSO­4 ;exmh-2.9.0/misc/mafe/help/mafe_buttons.gif0000644000170700017070000001204413201227060017757 0ustar valdisvaldisGIF89a¢B礶Üd~¼Tv»ld‚¼,Jtd¼ÆÔ}8… Ö±ÿ£ÝÁ@V¶þ›à PŸ VYIP Р@`ÅÊqC¿¾}û~ÆÎ¿ÏŸ~~ùýñ÷ˆy  #IYpA\ à >á dà …\¨A† n¨a ZЇlÀAˆà  p! .*H‚–ðÄ„XƒE\pqA/ÕæF!m iH†Ò䓈$2[~™$“L:©¥!QNéÇ#W.)æ–\J–+ltƒ ®¹`ƒkV¸¦ d'‰u^˜g‡hx¢ƒ Äx‚z¡ 4*ˆè‹ XÀ‹N\ð( FðÐÄIÀ•Š$©†! ²ˆ¨‹ b*#ù™Öé§¡ŠJª©þˆ :”*ꨣBb$‰¤ÊGšyðÁ°;ì ûÁ!(»ÊŽÐì°#@;, D›í°%lûA ( ®²&@®¹Ã¾€î/4ò˜à®#<˜ ÄŽ&á!Eò!˜L‚zÈ"¢k©fú æ’‘HÒpÔèªk¯1U°!‘œ1$‹@+nCû'”ŒÉ%/€ò –Ìr.ksÉ2Ç\€Ë pBÉ#º¬Â >]² ø\tÉ;]¯'|p ìÌC 5ð´PÄ ñ™æ†ˆd‰ˆÁ#¢ë$½Îú5¨‘PÉÛoïjÚªúimG‚±þÛˆÈv["³ ¸Î -ޏâ.0®¸†—¹à&Lo†Wžy†¿À¹àž¾Çç)ܱ )°PI©`IÔ,°|‰˜\@Z[´‚:6$d{Üq&Qú»O:ü¶$nÿ|[óqÉd'¸­7LjpBqÈ)» Êj`í |¾²ãÃ÷Ø*‹- ÚîµïÐAüåž«ìêÈðA%5äÿÁðß ?hM³ÀÂ<7d‰w4Û®&aTÅd>Ÿ:„&žä1I@‚‹°^Ý,&0HP¢3[&&±ˆ¿ýê2ˆáfCŒ@5$ r¸Ãê0‡þ-¨a hC"ÆÐ¨a唂¾ ‰1|¢“˜?Ô €• `þö`.î VãÁZp‡¡PÉ c3„ÛÖ‰M@"!4“×x‡±²•*“xãòøP¥&ñ.(|"XȉÐ^ ºç‚î‰ï‘Ã2 "I‚I毒”Ü– ÒwIMR-’ŸÌß'õW‰l‘ÒT—ÿºÅ§ Á<ØC[Te0Œ¡ð–$$<ñ7‹ýÑT¥Z„3 ºÉ$w[#"¢§7 òÒW‰dÁ '8Póp‰ §Mn~@"¸ûT€àà9('ût€q~`ídß2àÎ@œ,þ°'>çyƒÜ áêçêRW: ŽHLÓTæ~µÅ_nÕ!Ú=fêÊ{lÞ¨Øh¼bž 7ª¢#""QÈ‘Îͽ"/€ œ`M€Ó SÔÀM àÀK/ð@R4íÁOP¡^€¨F%ª¤. ƒ›þTLê͆ڧŸv@'øi%|*©Tõ•pÂOy âüb‹Å:+SqÂÄÄ(#@V%'yŒKf{ãwI±<4¯l  áI1ú̵€!°€,ðƒøà±@Hìcƒ€Åú@X¬€0Á?È@|P„`´¥åj Z A§uþ­Œ@Ù" ¶¯}n5\ x‚k}°# 6¸'-q„" b e¬˜jy6bÆ)MU]9¶+8N„„ÝãvÑ1 r—% p„ váJ”ÐÞ#,Á.íe}ÝË„   ‚Ü„$øÀ@`/€à„#4á þ/„³à'8x‚¹ð°à#F þï6 ÷6ôõ ¤Ðµ*™Jb,daxŸyA4æuæv±Û«cÚXbÄt掟Y <À+PA ) y Kî ”Ÿ\€) ` KÌVª`+S! ƒÂ—µ …*8Á ^¹‚þ¼B DFÌ@° œ#4Çy[I(ê =o Wp¼ò P¡Œ¡‹ÁèD0ÂÑ~ô£ÿ“èE7ZÒ‘†ô¢ù>6:Ó˜ž4B‘è4¹ pZ°'¨Ú[Hµ`­€YkÕ0Xu«] p!½@ÀkTؼæBª[ …( €ÙÆFv³½kˆ¢ÌnÁ(°°j-ˆ‚ ÁæB\Àì.¤º×Y¨¯÷ÀèG÷ÊðfMjà½hF`šÞóF ¾åðiFï6øîwš¾ðäº`È5  Oð€Á¿€…0hbà6 \02x`Õb(ÃÅþ9n†`‡\ ½î¸ ÂÀq2(| f`¹HQ  AYy®Ç`Š`gÁ 7GNñqŒ? ¿*–ÎôD ‚K‡ºÔQáh¨?龺ÕîèT0Âë¨ðz*œnõ«SêS_zšÎp´ýíng»Üç.w·Ûýí!€ûÛÑpèÝí|¿»Ûý÷»ÿý yüáˆÀ.%RAùÊ[þò”C*4yÎ_^óž÷<æ-úÌWXHCêUŸÖ§þ ªýë[¿úÙמö¬ÏýíuïzÞϾ÷¼÷}ðï ŠK¨¢øÅ7¾ò/Á|æ¯Âø-H>óUýæOßùÊGþò›þ/ýâ??û—–Ư†5Œßüç'¿úÉþò¯¿ýíw¿úã/ÿ÷¯¿þéŸÿýÙŸÿ6¨Áÿøÿg~ñçXm@€ˆ~m€¨€þg~Ø€(~l €êwè~Òèæ÷"8‚_£$x‚((‚é·À‚~¨€å·ôGoPƒnPƒopƒ8¨ƒ6؃7øƒ9„9ãGƒA„>˜„@¸„G8„åGƒ?È„õq„RH…M¸„Qx…9øƒDÈ~"ã‚úÇ2h‚%¸ô·hH~pÐ…ô‘†nø†jæ—ƒpX‡vh‡kè~æ'2ùg¸7¨xð'ˆ†xˆþƒ8~‰(ˆkx¸ˆ‰Š8‰ˆ¸‚k‚%¨ Ø~š¨‡ž†›( ø‰jЈ^8¸~©Ø‰d˜¤Èõç‡ü—‡­†}芮†åG‹ôQˆ¢8Š¢x‹º8ŠÃx~rÐ…î'2ÿ`ˆäçŒãµè‰ÁXŒ¡ø‰—ØŠ08†Öƒ+ˆ‹Ùˆ±h°ˆøGè‹ægŠç§Œû'Òˆ‰ÔX޶x~Žn°f¸û¸ÇX„_£‹ó8ŽH‡H~©ˆŽyèŒ{HjàŒÒû׆bX©X‰ñ—мøåx•ˆ”(¦H‘è‘yˆÒØŒy’©’!y’ã÷þ§8ëçŒiˆò¨m ª8~Ñ“ìwŒ˜h~t0t@j€”+¹”0iŒlø5 q“ Y“S©~&i’¹ ™Œ!•'i’$ ë'–‘;é)’rØŠs0äW”†_ùŒ@YŠkI‘j@–äþ|Ù”i•t))˜X)”3I“/)˜˜¨b™€åÇ—g˜Œñ )“mH0¨”ty)ٔ凙ù™x?™—‚Y—X¹““x“©•ÈØ˜L ã·“`H–æç’¤yë7’é–é'œi™©9˜v)>Y€i޼ ˜')ž‰†Ç˜Ê¸ŒÈ)‘ þ9b©€À€‘Žù±“q™O™”Fɉãg”œY”H Ÿãw”G‡¶Ù›2èbù“k`ž?YžAž§iž˜ÊŸ[)›• I~m¸‡ ‘ŒdYž¨ ¡>ù—øH~F9í§”Fù– ªží‰”Z)ò¸‡~ø¨¹¢+zšš—…Ùz¹ŸÉè´ØŽ1•7IˆÚ˜—ñ§¢¨i€* ¤ºY¡¼X‚蟅H¢jЖæç–k œó9~GŠ~*ê>©ŸpX¤ÍY¡y©¥ 8 »(Ñ™—]Ù ´é HJ–\Ú0j ¬©ŸÒI–p`¢­¨”è'œkP”Nz~ñù–ú§þˆˆ{ø~bÉÍ tZušŒŠø¢qê~Ùˆ£™ty¢Aº—ŽJp §> ›¶ ¥ ú¡Sª¡¥êx¤J€æé“¢ÈŸzÉ‚^X£^§,H–2É•³¹^–žø©3z¨‘)£vz—_—å—z — șꙤTЬíXDÚ›>š­( ©ä‰­ß9£»Ö™£s)—ÛÙ†<É“¹ê¢ú­êéÉ¡ƒê~Ú¤ÐʤO*Ÿ¡™ž ÑŽÿù¢¡Cú¯û ° Ц½:÷G’òÇ£ú·›Öz‹z‹+¹H©Ôš±HŒù¡²žx§ów¹£äg€“ˆþ–hhš ®šJô‡²ó›C)€H;«~X~?Û~,{C+³éwi©ë÷ ¯èŠ<ê?y‘$;UÉ«è†è'š [z(ƒé‡ ‰8ù‚ò—‡©h²”8ʉ‹"k±«ˆ+¶ùœ©’rëŒê‹lKŽ{˱æˆS ´×Yœ0 –*k|{~0¨~yˆeØ™T ¹nøŽÛ‘KY³+)‹»¸•ê“äÚ ™Z‹‹ø‘¬x“èGˆZ[’©™´iœ„ȪìÉ’ -yœ1‹‹ ù ¹“Q·i«~xY›­KjéˆehœÃ[µ ZŠxŠ—^ º…{œ‰¼²‘þË‚ŸK½i¼kx§ÞÛ½Þ{ŒÇ¾k8¾ßÛ½¢y¾àk¾ëÛ¾í+¾Gª¾ðk¾óK¾åë¾ê{¿ö;¿üwعK«¿è›¿÷Ë¾ç ¿áø¾¾<Àܽ!ˆ¿äûÀ L¿ø‹ÀúKÁæþ—ÓK‰¡±dû´îGˆd둯x"KÂëµ\‹“0ÜÂ"¶¤HÃ0h© Š À’›¸wxø‡‰»¼p¨·?|Äh8™Ðˆ½äJ½s ’bkœ6)»QìÁS,‘tÉ›ZŒœ‰XÅWŒÅåjŲˌl·T\½J{“þû¿Nü» ‹Ä¶‹†&™Š JÄUû¼ihÇp¼:L“^¹¦øÑûÁŒ¼´ ÆÉëš’«r9ÈL©ÈXìÈ©IÈX,Éq°–ü¹†|•olÈ J·T¹È ‰•šÊ ;Ê€ÌÉ£|ɪ̾‰ÈY\—n,Ê<ÌÄk³³<Æ=,˜¶L‰«ÜËIQËU;‰æúÊ ’ŸùÅ¿+•k˜Ç ÄMé’XÉ›éËÔ,jj˜³<ÊÒ ½€ü™×¼ÉJ+½•Ü»\Íæœ± λìÁ=ÜÆ¤ Ë(¹ºäwÎÁô|Ï—ŠË£»ÌÐÍYŒÏÐ}Ï·¬Í¨ šÐ ½ÐªLÊs ÏÉÐ=Ñ-nÌÎOüĽÑ-ÑL—Ò"ý;exmh-2.9.0/misc/mafe/help/mafe_distro.gif0000644000170700017070000002570613201227060017576 0ustar valdisvaldisGIF89a„äæäÔÚÜÔÞìÜâìÜÞäôúüŒŠŒ|†œ üþü”ž¬¤¢¤œ¦´¼¾¼4:<¬ª¬DFDÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!þCreated with The GIMP!ù ,þà'Ždižhª®lë¾l€,Ó5Ûµ ÿÀ pH,…º¤R¦D*ŸÐYt*ЯØìUJ«ª^ÀÖK+‹E_®Ú•êØév%…“Óà´:Îoïï4Z‚ƒ‚STO&S8o†‡nQa’“•J–zˆ„œ'xŒzy–^¥J~a“8m¦š ­I­²¡±¡“w®¢¶´·¼»_žÁZpµ˜”‹´®©Æ¹Ì{†yÎÉŒÈÊÓ|ÒͿٖÂÞ$ztPªOkäæÒËè¸j ðñIÕ÷®ðôaÕŒ™–øü¤+wÊÜ·N²¹!ØË”s Ó4J‘z*ÑH`@4PÔžt¤§‘]=)þíQ<éð_­e0j™Ç$Ô"Xº&:Ô©Î"º“Ud ¸ ã¼ŒÒŽ2ªƒfCJ3bävÍ&OROÀÈ4R’e&–'û-[ÕSàB_a˜>ZôY’”ÅÑ+ÐÕª¦’0’e†Õk:‰*%Ø Ä©Êrí¼\|5Y¿d}¡Ðµ!#¥¾¦ñŒêÓ÷n¼¦šI*½,Ï(ÆÒf–"/âaÆ s™j¸²•A?ò¬9ðî•írUƒÃ”‰Ú„pé6­ù)RºI_DJ’yÑæ¤£GORwZï•Ý6£ýFPš±ÃI$ø¶bïŽGÁ[ƒ­v•iœÏ :í6ì—Ÿs8rð0þA€ ‰ýå|yÜT{O݆[×à¤!l=ä Uèäµ_ÑÑ]I,R`Sõm¤sL¤È]‹s'cuõ%HIm Bäé‘…F5™õ2XQx–{ '‹ÌÙ·„ŽDfăPX¥Üs4:—%†VzéœÐÑ#VVhÃÏ6HZÓØ…5„Í+€=)Ÿ›G2ÖK–5$g#™Ñ‘Ä%‰˜ eã}BU‡(v9d¤ßiéàS§6ãMZ„‹\ØhU¼©ÉáW—þ¤Nò´f¨jñì`ª1®š˜©~&Ú«§Ú÷Ù‰¯²Å š0ÁFV¯:é¤VGäVO4 µ©„éKÛl*a„^[dþIðЖqÕîqe£ßVË­¶ãv âo²y¸Û°›1b†¶¹‚ϨñªËiZm™¹Ã´Ù6J¶Úþ;H­¸_Ä„Y’&œ+µ'ž@~p§ÃQ<l6{¹íƒn0k­¹”`2¸Öòû-e=„[2™'¿Œ°ÉüNÔ N¼þo‡M¸»i¥7™ä„ÅÐkÍ:u¢Wó>q‹²!5+ý„ÔýV%ºqØ&yC[(„±[ïhð™ 9ylš!1-¹õ„ëÅ´pW‹ŒÓæÖ=·! ¬.Ùv"ƒ):D¼Û DÏô2U-/Úµ,âøâÿЃ¨x Iâ‹ÁÒ`Æ<ÖvtOþž&xM”nú騧®úꬷîúë°Ç.ûì´×n»ì@ž[Ì#pÀïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐ+o@¨RlÍ×{øþ;ÛÏýðßÿýøÑ@¾ùÀŸ¿|øÆsï~ñì—/ÿúÝ7_zî<û†=¾#À2Í4ãh3ü€,`SvÀ’ð$ŠMÄÀ"p‚ Ä 3ÈA ^ ‚ ”é>¬œí®0¤û]$V(ºðgS{¡ —&ÃÚp…44ÄAª´e£0;Ð+B ²%dëÃ3öÂDcüª%tªH—d""ñŠSÌâ·ˆE.žÃŠVþᮚ…8¢¡0 àÞ[šã±]§;ºƒ§nø~玌KWe¸ÃåÏ;?èÝïô£½Lƒæ FpÖ0×$K=9™Å¤ɉ풓Ädæ~‹ˆ1ДӄYºñ‚*iOPæZ¨h ¨âÐÂzªôãWðèš&é¬^°”X.k¹Ë9ÝÒ2PÀýÁ.E£”ÒS¡fH«;´Ü¤K 2ZêÆGŒæÕ²Y˰èá“AZºØå0R•IÕ5ƒ™°RGV Mª »H¬GÃx2ÉOÑ“žú܇¹3ËñM<-ØO”&¥æ4ÚÑοˆ„¢-òN•Ìãþ6;— ÂõæfLÚH9*¹‰ð~èaXï ˜ówjÉ µ4Óÿ(F: ˜âh8Áä3eœ6õÈM4'0€0=W¯‚NåɄ)uŪ0¡•ʤ#À~^ÃH#õ&_·&jòIÿüizŒ$…>~ŠhݤæR0 † ˆ¢„”ªÅ'\M+¬Ä`jÖ"ƒÏ6Ö °E¬Hë©ÇEsz ³Q}Ó£-res:bÓµ¯0ê*P5ú€Ž68-OUÛԢ͓J-žÆ©;˦ð¯¢êP>S*·U¥ËT06©^H±¦ÕÉßÌêU±2·šÒXnµþËXö–'>RB…ø–~!ì»+Xä±°u£±Ù\SI˜Þĺw±â,¦úhEñt­–‰£ëm·u­g”kdS™ ¡ S¶É ­¬Oþ†ÊàËQAI*JýˆÞÉ ‚<@xk¢­ºm˜ªëÑt?¤7Ìy1¡lnZULb¸B¡t Œæ\<ÊŸb¸ZiÄmÔ6Õaþ¬&Ö¨/ÂÆÃm†u¶xRlH—LÒ2ƒ‚Ÿ¬Ô/·O¯‘ ÃÿaÓÐa¥] bØ\WèÊZTû ÕÁ ^íƒzãÖn*ë­ :ÁKq»Ï1žs–ó–Køf´]×¹r¼îŠŸ‹`+wÏ9Ø![­þë—âö¬Û5ßÅÚˆb¿y×N+m4[Ë$'—¾Ln/¨›Ú5¥NÏ„ë½&Fq çýÞ9°F{Ö–{æ†NÍf]™Ñ›æ\ïf„[3i,ç¨j˜;Qq†²Ô›ÃZoYnŒÍ ÉšbBúÚÓF±%|êÐÅ'–ØMS±­F£4´ )±uš‚"(bÈ÷º˜û3a1ŠdYZÔ¡>r¬Ñ¸Ôô¤Ú^…µ²¢b×îB¡$¥mÄ–d»ëN‘™×uJ-®!>qeY¯Í¶ì3ãl¶Ð@{,ZP£"d:A1ÂJ¸m³l?c;ºˆžöË -lëP˜

Œ%],·IC‰õ÷~íWŽ'SPÔÅ8!©wíØù‡Ö¨¶ À‡¬¨ ‰Xém x”îõwàà¤kˆþ7#`Nñ¸·lN©Mªö„™Œ©ŒJÈILƒq}VGZé5ûñ†;©ßèb;_ãmƒ8„'—,IŽ-é”®‘aÙ$5æh±pe®f•²q’•~ÞÆ`g„‰”´HunW 2IPµ(—íe‰9Yƒæ3Ÿ&dåð—Òøm¯T‘š~¨MD6@Ü&Z1x_XSy[l'‰ÆäKáÁh ˆ6“‰q’wy„yY”O yæK‡tf’– '†íuKz”<ôH™vum÷˜þȇ¶IµTv6[® Ž¡›h´™Œ§ ê}Ù a‚¨é•¦Y‘™HE–z©†„9•Õhþg¸$¹¦r‡ÆŠùKû hE蛘蒓g47a}fiÚÈ•n2pƒi`Mu&GTÃØ+Cjé‰ühúHes2“Y©Qlh›=£œ’Ö‹yÒ™ÑöI—»VšX£Èˆ.58aéxÒè:žt6d(ék9q&i -'Ÿ*é‰xÙ¤„ÆyŠ$š+nN9pÕ¸¡ÎÙxÞvržÖGû¢ýH”¢™ MY™Z³j€ñTù‘@Q‚¸§¥=êvÆÙžòø•zª`õ‚-6eginšŸ¨–¤DXFÊ¢¹‡ž*Žºä¤¿©P:PÕ„ã8©žæ¦ûõt–ò`ˆÉ3  þj†^é˜Ê¡Œf ~Z¢–y¡H2¨:9-¹Ùn'w–pš`4zšðÙB(} Ê¥<úš¢ó¦)Y6eÉž½y~C*¤uY‰z D(Ÿ °ªTʤö‡œå¡¢;©;x¸£M—iç•| ‹×)‹§JjÀ—jê9àYœ •A§ÑGtJ¬Òy§ºêž6Ú«4ÉOPF™‡úyÊú‡Y©y‡Â*mÿš«j’j—Ò­ŽÚ9”ÊšÕc‹˜ÚT¿8ª  ˆ÷ˆ¡gs†FFªyjªè ™Ñ8™ÝÖ®ƒSÂÆ­Ï¦”Ny¯C•ž7J˜ï –×:/ó¥£ ëšºð8¯!Éúv¸É¬þåùv‹­‘:±Àéiºa­| µVZ‹2Ë“–j}^Ês&öŠpYéz® (œ?[©I;¬ïj„ñ rúZdöʵd[€¤É¯¼Ê³n{,{˜{4´«“#)lûÙS='±/‹1³¤3+µQ»¤˜ƒìzµì¨VÉ`¬{­ŸZ²©‰T%û'[¦¢{oz±ÚÚ“'J›i°µ[85K··m÷ê©§Û¯zû`Ø$BÜé¶ì£Î ©@ª¤¢ÚšÊ ­e1¤J Ë:µÌû¸º†,¦Û—G ¡\«š‰Y”"”}y__;®Z®¥‹²fk¦H¦“ë…Ø¶! ¼Ù&¥Š}I¡Í·ž€ÉþŒ™›·{Z“>4¥‹?‹¥:ù¥Ä´ŠJm‡û§æ5­Ú¼ŽË›8 [j+½ Œ ó£i¸íÑ ç2ŒÂ˘¬¢r'¾"Œ¾!LKÂÞ³e½j™{ 9§°Û“ÚÖºu‡·þª·ªç»¶øØ|âÙ¾6'Y(²F¯+wŒ&ø´&‰  ü´½aµ¸k‚ÔË ™ÙÂRæ¾°²ŠÊ½[jÄeˆ¶ã;ºØ¹^ȦꚘê{ ‚ ¤Xœ˜0lÃêbJ»¯÷{Ãù‡ªºš+Ãû]Ó­½½L¥òöÕP”Ê}]¥·ÍÀ‰ü–‰ÆÛëÍãàèÝÖ…ûß[<ÐBö½Q¾¡Ù=n4¼ˆ®j1ñáòÊØ–ݾ»¦Sì­NÚ¡=—PŒÚ:Í"ýà1.âÙlÀðüjæœâòÍâ{íÀs´šÝ™±ù- UÝÎÁDªØ#n˜ŒÑmà@.ÔF¤à.ëÞ‰‘PšÝÅíÖ€ Wí«Q~áS.ΧÝÒæü¢\î¬$îÅpàϪâeþ¾âýËö,Á¾]'€®å.ƒÝ+®]Ìã+Õ?ŽçíÐ]”EH,¶eÉ~Æ+Ý—ü¾³›ÉM>Ï´LoUþÑÄFã¬,Y‰ZêÝ´`QÜbÞ¸œÔæzßj9é¿Üß—^𗮨Zç­>î¯>Ô0ŽÒT– £^ãÛ¼àðüë4{è®ÝÝ·»è"9äL-´â†äÚ#Ûìý¼°]¼G¼É™ŽµÑÎéÑÈçÐê²îÇ~ܦŽêÆ :P½ê>.Ùã.Ôo³Üç^Në«ítÖ1œZñWâPnágý‡o½•Íáž Æ^ÍÈ>ïìµì¹æ]ßоé>óéë–´æþúSë ®íï±<²ÆìØ,îoE<¢çn®–³ 3v›½äM ïUÑÞÁ.Ú+?å1yßV._üž!®¹s^ijÊÓDÜâ’Næó=©FÔ½mœšõ€¼¥þŒã¿óžyZA.ÖŽñÿ©Ã@ëñ³>FoØLò‰nÝUÊò“ïÝ–Ÿ?ÃŽîßÁ÷éðÊÞ°Ìþ« [ð=?ߎ»±ÔãD¿Â4äožô?û†ù…òîNîÌÍÎÐëÑ螺3Üì.è¸þî*ˆ³w«ò˜§gÓ²Þw¯ßï&®ÞŸì9­º@ÃókOßÒNÊÕªðE­÷}Þïβ¯Íoþxx¶¬þõ»¯€jÝñÅ¿VwòøÜù&mü»–Ú/MïÀÎÝ IŽ"P[–')¸òìÆ6]ÊßûC*e8L6Ô ç‚rͧ±–Ì1¡Ë+*'£ÚªL爛ĎËQ3í•Þ´.–!è_¹ó®Í§ÿ T¤áÁÝÝÍ™Õ !âSá Ó¡Õ–Îáà¤å“[æ¤fÛ¦gç%äcB‹RèãcšdâÞOPà"êé,"eíìînUªn¡â/îp¨¨î!Ó \²°Rå®kO_ `á³bð¢Œ/™·nx''#žá­¹ÚùºaÚü{%+‰J30ø{ï)5¬¬¾\bfq%/Hñ~•“V þÓ'ˆéQŒdÑ -EÍT8$–ìâ‹~Öþä1ãBqÈLŽyôí$¼‡ÁÜ53¾*¤L¡«i“5 *bá¥-TAz/ 4*¥bӜ۬·ÆÝÕvfX¢8±ñ ™0Spùég‘FlƄɖ¦:ƒ NÌelȺ óJìkר ž(á–©#è¿¢¥ýýXóæ:4¢BÞªÒgå»+ ½´WJNOÍŒ= èNUǶ&-]¥5®Ko¥"e•UÜ´µþe•ãÞÔ‹uç@< *® öe®4²”Ö}+êu¾ØW6ò5©GÉO¸‰ö€Z̓¥VyË {þ|êéΧoŸðÑÉiJÅÁÝ~³"å%VD@©á¤>”QÅOQeõQSî–Ûmrw„-pScóRy¦•T^˹–liŸ^и8v1îUNcHÈ ÐU§ †-±‡PB(–ÜcÚ—YwÏaÚŽÖG~u„ò“Çüw "¢WƒUÂ'_\«SÌl¦ó–„iꦦ—ºØ#X[Â1è’8@u1UÙ\x 9²Ù^Mf7ã …ÖU_u$𔦇y§‘Xdm”ÖGÏp,Vz¤“÷!¥pú½Ù_›±!¹Ã+Ç ¹ ;N𒇝±j C¼¡˜EXkêj!…–þuw†·>cYº@ªezÝ{¢s¶EEfÛ]x¡´ÕÊh(µŒªã´ õhÑ3Þ9Ü¥Föé\bÁZ_³O~ú.˜sdž¾6¸¤?h ®¦ØÚ·­±% ™.›ˆ­l&¼kœcŒ°m¼s».© I ‘ãY«ž¯’Û)ŒuË•µ„¶xèj"Fï­í‰çèÕ ëñ¹æÊÔ)¦4HŒoÇ‚º 2’í–°©öB e%ÕŒË`—F+Y›‚þaÈ'¯/¿£p¯Ylb£Š©.®ª$ó5#>ûå¦p½Up²àÒ'mx™2¶pËíÄ/ý-Úg(­*ÆßœvÍ>Åíi¼þƒÿÌ3âFB¥Ó-~Ù$mé,Åà!¼élüR¼yÖg^ͰÖXOˆ“>DOœßÇÇCD8§Ç\ßÛ3Ìîµ$9Œ>Ó}òïÁS—r^»èíæìûÒ¬¸jœÉØä ^=Ò@ï© p‘›Š³ °Ëc«mF­¼¬¸öÓ¡7::¯[“~zùAð™ ¶‡½?$“Ð|Ù.'—¾EmÌz^ã‚w¸Í­duk '~'"Ã5d‚ø‡§+5FSÙ«`ÿ´ç8~{aN¼æ½³ï‘2èö¢ÎåÃ|‹ÖD—Óñt¢‹KŽ"†9±éMþРB”6ŽÝþŠj±Iß}ç@àM±wÝÂä¦ÅÄýµï0/ _ ‡:èÕì=Äé”ÐJ˜À5ð7@K˜Sý(vaZýp×>õkVˆVß·Ãùõ°jïs‚ ­6°…ðE|p Aç¯0’»–Ø@L†±&yÌL,8Ä/ñb¼à 4<ˆ®—Ï>i„ãÔÈœD«*.c\q¾˜<¶lˆª¡áU¡¬@Ê)~…\X•nø„O*Ò—%ì¨Úil‰¼kVTìŸ@ÌcUüfŒªcƒDRf죊!¾È•ëEeÄei)6Â’]kÑÖÊü¸@\^AšS_âj— >ê&þyÄDß IH>q^Îø:ã¿è’Ü^0k±6hÊn–ç&çÖÎõÙo‚ÈsJ]lÍ¥ î2Ösg(…¹Ç ÍS6¥ivZ/=òNNP'—x©¹0ýŠaÒÏ=êš„"³©î{’ꄺ}q¥HÌØòÚ(PFmð)€Êi75)V*Z„pêÊb9Ÿuι ¢–Ô"/÷I¶ÝkæTŸ©ÅRÊ®«Õ´^bûd]íqó³œi_Jϰì¤[\k®\ɾֵz{§%vV=ÚÆ²ž®¼'Rû*GÖÎ3ÔEŽ>eH‹V.ö´ Ý£™ÙØÒ-t¿W@+N+ÑËÐrm#à$‡YIö"¬`4BehÁ ¼¢Ѥï%_J ‘AS¶NŒq%!Vib_úâµ¾ÁÅP,"»B— >çŒ:Tâ.U%M ª!‹¹Ü;uÂË„£‰ÓKTé6fÅÕMbaµz]+ѵšLžwAKÖMv>1³JžGðÂí}1?©gÛÌÖ¸Î÷þ­3;Çþï¿D€ -èAºÐ†>4¢­èE3ºÑŽ~t¢ñ7ÚX1’N.úñ ­éMsºÓžþ4¨ÝÒ¿¢M%ø[†]ŠU³€Õ÷{5bÝêYóÖ¶–u­Y­ë[»ºÖ´~õ¯omëa»šØÀÞ5²…ìe+»ÙÇþõ²s”?ç |•[Ùý˜­mXG»Ù Ðõ¶ÃýmeƒÛÛÚ··Óîu«»Ý‡f5kTËŽö¾7¾ó­ï}ó»ßþþ7À.ð¼à?¸½ûsËXuÑǘ¶7ˆñL¼â¿8Å1nñŒs|ãÿxÇ5.ò“Üã#7¹ÉK~ò•«¼å)þ9ËaÎñ{ON1å3½±‹…ç>ï9ÐQÐó‡ýÜçD:Ò¾ó£ ½èIºÓ£õ©K½êIX²žõTïOÂłƵ24&ãijf?ËÔÐn0³ŸCÌEî’ `蹡,µrsNñ¦íD7ÂYþÞXl½ï)úá·ÎtÃûAð#8záOøÉ;žîM|oùÊk¾ó™ÿ<æCùÁŸ¥^#HäévÅ”~ì­½ëm€öÖ×cçc¯=îoo{ÝçÞò³}ía|àï¾çÃ?~ñ}¯|áïž÷o°¹3-½#€î´÷ƒÚ³Ï×ßë^í8î¾ò‰Ÿ|ð;_û|=þùe¯~ô÷Þòí7ÿðýŽñ¾4SÃzá1‚Õ@í$=?öñI 4žžÊ0Ÿý  lY_ F`J îM V R Ý û)„<—:ÄØõè]ÿ- ‡¨ÌAì–qÈ· ÙÈ%!• þ BK Π æ îmä@Žé–Ž`–¼¡ ›Y†` 0R¼•Õ‚É@Ð7 Œ˜8ÛU¡^!ž tà”\°ƒ”õM[ú¨RZÑNSˆL(ÉÅü™ƒ$ˆÅÎ!®Ð¡Ö!š#ÉÅš`‡€YÍðŸzÄ ±Î³ôÆ|×aå× ¬a>"$Z¡o4þŠÅQUMŸ•éÜ!rY[ ÊÙ9é zKY5â%¦" ®"*²""´",Ž­BîT|-BþNØEœz˜¡KyŽ©ÑŒc€Ø.Ù˜1bD¡¼ %vX º 6 ¶ 7,ažPV~Î Æ72ØŸˆ"raŒ¾pq þ­Î€½V¨¢Ž(ÅPŸm¢ª=[²q° [°‰›^®Ú·®AÛ_¶`òša&&»-¦°&²=&^Öß8$’K$^&ff¦fn&gv¦gb¦÷­äM‚¸ôÜ[ZªæF¨f£ýkš¸e2†Q® cBf¹%(fdÞ& ì¦ogbn‰cò¦og^~à€LÛ}¦Ù¥Å (tb¡t>guF¢b`gvÚÀuRgw’€tÒC–<ßþñBàÿ­§Ï!e °'0]|F|R~Æ|æg}Ò'ê'ª€{öÇ~ú'²çPhR‚€btAs–T&ßõ½ßí©xF…fàv ù¡ÝuÍj`ˆŽ¨†ºÅah†Š(…²Ÿ‰–àý ù…_À‰öEy‹û  ŽŠhÒÑ‚’(àÖMžÀ}² &i‰ª¨3l§D“^àå@€Ré†ÒžŒ]ƒÒfiBèŠ:‡¦]í}hŽ®_Œ¦Ÿõ]h`„©›Ž)‹ÂßÞµiœ¢é›rߜ‰ߥˆ²A²Bˆ˜§zög~¶ènÂ*œÊž“úþÙÁñ …t–:ümž“6Ÿ@€§JIté©=èéÍ,,¨ªIz;0¨‹ÆÁÌê¬ÀžŠÌ9IL˜iœjª®* œªý¹j×%Þl*ª&멲êb ëàÅ[øA F4ÀY@°*ŸÎÝŸ"A ‹ 8+ üê\í™ÀªkÀúƒÔц«¶@ªúÁ¼>㉄ƒ…Æj 0€ Ü«lA—bX*ݱjøëh«&£¨:܃fȸ枪^+¾¶Æ´’J „t¼Ä°ë°©)øëΑl(¬D,$Èè€È²LÅö+ÂZ‚¿B*°f£xä‹þ–@²Ž¶ ìOŒç ݵ@½ò¬e(KŠÀ¦¦ÀHüŸà]€y´,½¾¬ÎÚ+ÛÅc‘Ñà ,mÍÖÞx_°> Ã^‘&jÏ©*ÊŽ­æ ä ¥—B »ÖÑ®èd+«¢êªêíª’kµªê²–Õ’@$ÀÇîÇ>­&€ ÐjâÖ*âJ-­²+‚ÎlûkàNÛΫ¿úª쬳ú*³fl0À’ì²¾¬ê¦ª¿ €²«çŠ'q‚çØjk¸Â® Ä® ˆ®ì¢bZ>(ŽÄAØ‚^ߎ+«’ëæ’+½’쯞- |ÆX»ÎjãÁJn4Yo­f/Ób/»Âꛬªþö 0oϯ«ú2/ꚯì>­Ñò-ò¯ýҫκ/ºÆPïðN¬ lÍÖ/Ûò¢Ž’l0¼ìɦ€ã/ÖÞ.ÖÒ(¿bïPXo÷À¬»J- L/ájžõîkø*°BXí—n=°ªÏëñ¬ì†¯ÛŸÚÒéÒëíÖêê0 ÓhõÑ)ã/ ôìïù¯w.ç£X&„*oXë×Öìð†+ö 0 +ø¶iãžÅŒÀôÎ-­V¯ãvoôTî½ZqÍÞîðîÿÞðÄVm¸¶o²ÎlĽÉ¿²1—/°½–ïÎ^±ÁÎñæ¢qÏqé-ººþ€@† , oÏ1¯ ˜,»1ûpºf°7îÎm°5«ëÐ îËÞÈùN0ß q_2ëª0_-mê60_U¬Õê,·Þà¦ðË ðÌ®rŸ,ÉÖñ|«k° ë°ÿJq¯ž…7oóR­'SÝio=ôÁ[ðÇݺöÁ£Vmîâ19§ñ¯Ž&çíë5¯·ì£³2÷ê ‹s°úñò¦25›nÚ^m ¼pËo;Κ}© Ë+¹¦ïæ¢jû*l «í*EŽeïäÒ*ÓRoW4õJ´n0L+xô!#¯H;tßârùï+;pJkr›*´¯fkí±®£´þŸlŲ忩àtçò±Kßs?Ÿô¯²±à"€Úáµñï÷¥©–Vr…"(òEà"߆Và¦zŸ”²ŸØÂ‚ò4î…jcuî )ø‰õš– Á–5šN*_5/àñ5õïEðØ n²5ÈÚÀÜrp|oüÅ07ŸZK(† ó{hDt`ã ì!^T+¶ÄÚ^]£_Þì8«öù î© ¦l.ö±iZ/écžT3ˆóñí=ï™õç0QàÃüè\ꙺ*í³@‡v £Þ¶ téëXL© e|ª¶ ð"c“uŠVµeÇ6‡ïZRÝ!ÿÔÃV?þ¯îBbžMÆÅàf6p9Œ%Ì)#ov›~ƒ@þ‚ÓŽ]†sì Sek/\1œx$¦AЭm烔¹ã\éqÅ‹J's~édŸä^y•÷Ñ€GKuñkÏЃmwWÞ!A²Ê®VðPÂÕSÆ^×B¥Ùà LSÅØÉÐÆ/<‘ã% ’ׯÓ„ƒ2N‚~{¡‡ÅøÓ>Ô’‚¾+\é6-¬¶`HaAéBÄ©ByôuŽ]ÜÄ…\””gÜ”Ï\¬âÛ•ƒÍéÛ”Gù•ë4Æ9™“œÊ…¹—“y©Bœ•ky—³9—“9š¯9–Ï\œ·ùÆ‘ù+Bì9zEš§ù–×y¾}ùn¾9›wþy ú cœ=,z•ú¡GºÈY\žgœåìÛ+º£ËùÅ]º¡‡9¨CzÄUAP8@ì)ž£öÐñÝC¡úª#ݪ£'«O[ëk_ö´-ÞÒízB„(¯+­;­£ö­³º¬ é³ {í1¯Û$5ÀÌÝfnµfZ»>a¡_&¶ ÇåÎhx ÷=ª¢¸?â#Pƒ Ì­kë êk~ºûÞ¡k‹h'‡+Ô;ÕØûàù»qÉ;DŒ" þß ?æ€ê«Ú@è¡`N‹Ý ó)ã’Eb|äo†íû@cêHù+iwê±Kª²Ó*Ûh˜ËÆÜ!½£)`Cøjkï}÷K–÷áyÙ¨+Ç$l|"3&/t¤! ‹@á-¸åL0„îë-ʹâJäf\i+“?Aä„<Î2&,9Ù×µr:+§à¥TÏ¥t=e¨9c¤7fß±bH}‡á“ØqT°ÁøóØ›”ò-·þ[߉bZ)Z®¤c .ø²KN¢W$²Õ›Cx·œ>SlÑÖV©¶„“ü +l¿Í)–”>ðÆ[œqÉ3Ø"ÈtW¨³¸&{ç[†§™-[ª#bê[àåá¬S2»Ö Àù觯þúì·ïþûðÇ/ÿüô×oÿýøÓõ å HÀð€L ÈÀ:ðŒ €Á©çuN 2ÈÀЃa?@Š0&,! Â:Ð…-4  W8Cz°†(Táw¸ÂêЇç æÔÀ0îˆH|œá ç ê4NqU Ž¿15ÈArIÌbþ¡ôÈ‘‹N´¢µh‡)š±‹XŒ"רD6r}#æÚÀAÔÙ±w¦»#-x§Ç>uÀó£ 1ÈAÂñ=<¢Ô8ø¬à¦»KŒW&†J"N-“t¤&_B†´“X¡&7©IHj£’¤tâLÉÅUZŽñø=æxxPaõ¢¿ô¼Î2''ÉK0‰-Y‚6:¤a¢Q>"p/ý RÝB64Qí"]ù‹m¶i;œH§7‘á&NÄI½“RTÉ3‘&ËËШ¥™Q¨£Â ®ÒÌÍ—;S‘e–¥©²iÚRì¾¥m?F^ b–¹j—l˜¹œý°î·É%];Ó×5EݬM—ÑNi)Ë{–¡ ¯\&-ŽªD [#³Dd8 ~ø Úµ^¨^9ˆSòUYæ§ivlbö/;çJ¬Ç{øJ& 2!TpIIR¤¥œ­¹›}iš#õ¡øy [— imÍ@:¯° ;U¡¤4œ0–†"镪ˆ&Ù•¤’sY”^*m:0éjâ ¥>™Ÿþ$—&§£uI ¨¨\8–Ì9›žöú`–Và)SXc#žµ‹ù‘ûÃz 8ÌéŽ_‰ŸÄˆ#þÆ4I©Tâ¥xæ¤8ÆOs¹¨bʤZ¦Õ³ª¯y” ‘dž3‘”‰:]¬†"7Ù!Ùl™™Y¥šJ£•©’Y¬Wò’=*ROµ6÷4àö Úr’ª)9d®Ù¤Ú§RvcF*Šaó’§Õ‚ sŸ„Xží…vjœ“Y~ªv¦-©£Š>Q8¯¿¢¬ÕWöÁ0¤()¹6|âé}³§Ðú¤~ „ÚÈš¼rwxY¡`hrGÌSlO¸SçÔs/j9h:©•qòˆ~í Du>X¥^H‘TwsteÒ.1ÛT3kQj¡$Ò¢8{ž&ûúŒ ûÍ ž–þšG¡&×wŽvREvŠòh˜©¨Ÿ¨¤Ãʨèú޶……ÄZWkŠ²ÜŠz¨¯;6\‚ò%}—–pU“;²Dó¬1j­A ‚–ª­É›§ž’®öÑW:xÙg˜‡2˜rå,:è<ƒ1$ûtˆ˜™M'8‰¯»ìç[Q[²Å£ûJ1¿‰{Ïr\Ûj<ÉÑg :€v pAË®‡ž:A¨Z–»Vx襖Ìò.o •Â’³z¥1ÕZ|l ‡¬;’™êœk(¨²â·¤–›Nv0ó2Õâ!;ˆpƒlTÚžª k[y®˜º ÙºRjA´ ‹$z(UÔ K` Úa‹ôþ˜rõÑ©tI…X¬ZK©Tj™£p@³Ì[m^2h6©¤•Ägõ]è± ²/F‡ i·Bˆ‡WÇ?áˆE„^³„Áã6b³`o‹©£1~ág—î%¯ +ÂÆ{HÜ  $÷¿cË¥nC†jä‹pŠZ§·Â§nHž«+” <¯¥˜Û螀ٷ'ŠGHèt‚ µ“rœ²V¼ÀûÀ7ü¸),wÇ{¯#k°8&A§a0JúUÇ’‘B»E ¢?|x¬ÊžŒ—{©U:L‰,`)uh»‹•÷0U1²}’Ul…oW£Í¥¿ÅXÂÃK5°è”:Žg½’J ܧ¯¶¤³º°þßÛ†âKwœ*¨\»ÕvޝÑd’°,:¿ÏÈ÷–¦ÉY¸ÀšÂ‘[¯Í7¼DSǰȆs6B½“Z…å¦g¥û¯:Œº˜¼½×:¨¬ pœÈ¶*»Ã’þGP®»µ e,º¸ŸZiÉ\ ¹¯|©Xl¯A\›Œ¹;¦P¾æxÆœ†§ÂÌÈãæÆ­Œ§éF·mzk{|´ªŸ:®ž¹”I°”*õR/Å* Д‹æ+0úb\O¾œµU˶ù E%‰±Üæ\GšË{C1 "Žâ¬Í™†Ž›ª <ÎÆ—­ªuF‹ÈD[ªyX;Óy¾l¢¾™&i2˜·ëTF{!ªŒ¬Y¸þ¸ˆÜ½Û }~&H Z Î\§-Ë33Ÿò)/Ö×0«2&yªwUÁî¼­Äœ’<ûÃYÝ[ù,I°ªu€IÓÕ—0nÕíòÖ¡7°N| P ©ÛŒ­LzÔ$è—íµ£k£_ÃÔùÖLEŽºë#×ù™Åy“Æ—¼Àãæ³… ´Å¾²ðÒ‘ÚÃSšfà#Ò÷2Ñ»7}^¸‡^Û¸®Å¶l¿ŠÈÁŃ|¿Ž·…’Ù¿`Ù0¹¾c˜eX0ÀLÀzÍ ¼Ïü)¹¬qÁÇ †ÒïkdzcûVþÈ [ÆÛ* –S˜ÊŠ Å&ÙTK²ƒœsú›ÃL­ÂF\ 5þ£=ÖÁš0”#<.:Y;ÌVx€•=ÖQ:„“}~t{±(èÐ+4“ë·Ÿ¢jÒ)Â+²ï*£`Ob™ŽBëWª :gtÉÞËÈ­J)ŽÍ½ýÍÆLæªö±Ü8Ë Ê×f±ø¼ Xç Ú|¼ÐÅ»ÚîÃG Û7z¼ú¥ÂúmyD@QhªøEº¿à®¼op«·!ûŸà›’É|ü}ÌúCÎX6ÁSÆÏ`«ŒzDÝFÞþœÒ¨Îˉ …Þ—m ®¹Øá°fºÉÝÚà+Ö1mx{;Ž}âåŒÞþ,íÑyÌæÀ­±íÊŸo×àAnÞþå ‰ ÓAMÈ!i´DÇ…­(†bš]]ßð\nkl~wéÕ„⛌O-mâŠqµÔkÞÁ¯X ýa”ˆhã7ŒãR,È[;cÍO –ò:éj¸ŽtK'tY&ÐÒHGÐ!bÞû&ÉHꆕŒ× Ù}ë€>¾V·ièI ÑjéukYÐJ×T-¤ üÓ¬ÚÜ=æM‡Â—zіΦ¡¢gŽ¡“q¥*¯"“‡rð×™îºð%ß_»Ã¦®ÙOÖýíÉ)Îßì¹â¹È¡Öë*šûÌ.רqSÒèH“Ímx×)×h^¼áŒkêê,ÿÔ¹$#oþ{É›¹§¶lÝŸ¥Þ“§Þ<òlÂŒÍê+mó êÜWQ¥/˜›v«UØæ)z÷, £œöîǾN2m¿;^µÅ¾©&æßÃ*Æ,Rõ •^Ïòy--µKŸñòVVœí¨¼í„ÎÍP^ÙR^óµä­Ø¤·W€U†¸ÉÛºMݤ <¯ÆbÔ`J¼¬Zs”îòr]VJ=9.lÅÐãŒ?{© ù[Z0ùK e/ñOßFOñ_ î_Áã^ÖD ¶+}YïÌLƒ@Z F©@Ü¿[×ÚÑ’^ÅßúÉs²È«Ê+y€}-p–rv tJg«¨DRôhŒ".õ™þñÕØÀgíÒɬ2ûœþ7iÙ„ë”Äl¡Æ­Ð—ÆÐcµ »Ÿ Œ uVz±¶xl©" …㨯«Z ]Y{n<ןB8&›¡^,¢©,.=µXG3QE3Vcu¸2×cUü䤬«b)àƒJ­[/õ Fîì¸@¸™š®#´©&¹+8,´Dš¿&º£«ÂÉÆÈ§6¬8˜‘°¡ÀªÆ¯¯ Ò‰;»žŸ Q¢B³ÌCÈÇDz¢®YH^Ë\ÒÒb±JãäFXŠÏ¤ãS2e[SŠÕ‚’ %¸Á$àÒGïL\¿³r®ØuÌKÓÜrê@fÈZÏ€Þ[xþjBdJ®åh…H‚ÿÀÔ¢Ó¯€Aég. ²sYÎÕª'˜´Œ ¥)‘D”!t݉“06 ȃI¡Œoñ õ¸²É·_‹Ø ө馸£ä(Ü5‚¡ÐeC]HÃ%6Ûú(pÀË ‘Ñ$a™—ŽbO”è@Ž-µ g¹}OÎƯ‚3©rÝÉ­‹*¡€«y<¡YÀ0×®†k*V¢¸GáćðE[LSÐv åm,ÂqÓ[ÐF‰X²G¢¤’“fÅ•õù°Ë‚ÛÈãUrW®nç¹]áñÄ¢MÅ]‹Y¥-ËDC¢Ü©·š¼ §}FÒŒ úæ"rCŸ‚´h*©ð‹ÇÈ#ûŵ[,¡‡É´8€-«˜Ì-6Ó­ Ú¸:á¿qôÃ’³Õò0„_Üj‡'ëJ$n¾fN[º½6©«µ`;³Ë1iÓ½l3TGµ9‹³Wn2»BólD8/SÏ9¡ñ¤$ çŒORK…”c…¹ b< XþíQXÃ;A0%<Š®•Oá[¹éäò(XQIZ#+;]KÈm aF˜øÈê¯Îdã‡Âë±ÂBD©5éxïÏ?¯´EΕØ+=5-þÖ¥ŽÓª’!U µÖÑ$öeÃ0~wMC`{EÃa=¼ôœ„v˜Ù°8UÀ7[´ó/䀖»­^=âAk‘ÍJsv‚rt‡ÌÉç‚CòVyŒfð7[RyzR]* dEÕB!XGf#`j\³o"Yܵb_SþªDÊÞԵʻ8Vºåúäs,ìHÕˆ˜qåÖzÄyÅiÐfª‚)…ùL=‰5Ñþäs÷4‹l“]M ôU;~'°7é[s«._˜^VIʉ­“Ø$³Þ:SLç%rQÙ¸*Ä…NßT/pŸWÞ ×Ë;WúÔ{SתÙ*“šËTîÕ®ð€ÉõCu^#â•(á±×ºŸOÖjæ Þ,ÏÍý‚šÉ‹q¯nK=¤rj–tÑùQ•ÝÎüõmyÒ¸c–ß÷s>m*\±Þmì*ØÒ!äÅl¨ÙÙuj'¹x¯-(‰}–µ¼>)ÒSN¨¬†5 @Çö¿×µŽ@!!Ü~E·&9"zMËÙú4ŤNtÍß|b/Ôaà)] þR³=zeK{ÜV²É¹,~U¡DyMYTKð88:­ôm1ã“ }Õ9×E-…²Žó X¤vMÃ~]›½ÎW¬Á€Ò@^½<„72¬„O  Ç&=‚ˆjÕ[Aå<†¥y SÅØ>ÅáÎ\Ðà_“úѾffq^t_åÜ8¿qVZ›U^øF™iPxø"B26«ÉÏDï@àÊÂX.BžËˆ´Ü²®FÁ)™t'jcŒâˆ ˜pyJr„eÖ>ON1}òC!ìvJ¶po¼›e&ñ§4Œqí˜:(ˆe¾tQêw~â,‹•#c{LI/‰þ©2C®_´R. D´&™®\&1“ìçuR¨7ɲË6þ®i¬ß»Ä)/ ¥’`óß³8Á·8nulãO¤âeR EPz¦BçIquÏü2˜Ftš"áè¬Àܨlsz üœcIMJíd›ô^4—8F¤š1JL!ÙÝ"J/SæÐUH;ÇLc¶ô–+ýâCµðPQõ´›N”  éÅø ³‰ ÍÒUxÌŽmµTÎ\4•Ó¡ÞΚ+µ+“*M!1…  '(*·"’O|gü’K‘&ñ޵ë]cçO»~Í¡hõ`?WOJ$6Zqmϸ„ Ü Ñ´/ó[“¤&þVsa­µÜåiR÷»Œ6Ô‰-Ü/ÑçNïAL«•kM×zœ…•ôT‘Äôɦ՗6± oõÐwõ²¤˜dPgK)“êϱ—=£DùÈ„5ön¤ÙUðÆIN i‘’]U a»ÊB¹êR³õ9 s]:O™‘’Žlì,[ãÖ·zÐi²µeƒ‰F·­wšzeiôœú]mªñ]ZÌæŸÀÉQŽ"X±¯`lHAX=õõQ«•,ó¢;ÞÓÂT¸jÍg8™ÕÏý&MÄ£ÝÏji[¾ƒÒv -ùûÔTNT€Ù¼Nàáâ®S,å-}»ÜÐ|ñ,J”é$ã”rzûls¯gšþÍe—­ÿ")D¬Sì~A»1¾hü€‚á;³Ì¡0^0(Ë[`=p3–žû+•†ðfWͪ•ù3·zUŸš˜ÑaíïÃÈúÒ0Kd˜Å æ@ü¬+p³+ IMTlª8^gN.K/\, 3°¶¥”ó’Ï\H +C[lEë> ¶3r/6°Ìç_0ƒ?¥gU OO×ê º¦ÑH+ KWª‘Þ"C\dˆ¦“½ î°†II2(6•Ú[µ{»f6+ù•‘…±—1Ùµ´º#X®ì³ü\5'Ó†&‚»¯KÚÃîÙŸ>!{®”gÇ*ܨ¾ò3nE©ÓþÇÃý,ïFáë]þ·R¾m£/hixßI5‰¸¤´q/x1³’d¦É>oŽòjǹäìÛÄH܃ê G4Ûrsƒ [蘖/kÛóÆ×›œ_«×<•tijZGz[º8”…¬eíùòh7û¹ì¾±Ë…ûJ àœÇnzº¡l“wÜF–šíRˆÇÜ©ª|*ÌxFew[Þe?b5ºYìNž×å—^a ã­u¯KE§r´JYcåàò™s=‰Ô8ïÂ:ôï.=“\q|ªO°êÕ›èu êÀ‹|Ñk5ïÙGÍÕvªã« l9´Á<ðtçi¦·%°3‡©%µ‹:¿<§+Þúªg”f„Õ| Ñ«ç.áÀZþÔ[âuzë ‘ù'ˆÄ¾®:°­?ij˜ˆ\ßyâeŒïâeb"ã§Ùz ðW[|å¢õÞ·¸#2¤{-¥ú$¼›½@ƒÛK½¿ò¸FŠ:Á3+›’7Žb\“'uC.@›%}®+3—r®4û²Âú@Šy¯3„ë=Öò°ƒq¸P¢½B6•3/¿ë4°™¡Á+Bû³¨šªÌ‹ª²£v“»½" Ü/´¿…¾Sš¿‹b¶¯Ë L>Ò¹¶ƒ8£{& »5Uc–ék<¼!¤›¥ã¡¨[«µ‚Ë?©?ª{1Yêºs4ÄÃ@Gs?šs"?t=4¥ÎÁ±h£<þðK°fØ¿§i;’ÛZ‚»!û¶ 7T¢¦¢ò¼¥ÐAÖë»B#CB9¼½¬3<& /ÂR1HÓ@2ÜÀ²ªÂW“Bèª<~ƒžÍ›Cöâ“Ò/j GmˆÑø¬RXùRdS0õ25Q2]Ó1mS1}Ó0ýÐ3-S:eS85Ó:-;E¤Á8¿Ú¶þ€@8'¡9Q Ý4~q”3eÔX9ÔVATQTI5ÐHuÔH5šLMÔEEÔ4íÔQœCXM=ñ2´ÂèR"™LmH}U'˜Ó"¾.€UMµUVSÄ™Ó#«ÕÁÕ_Õo‰ÔÓ¡ØIü3€Ò¡*+ÔÒ)Ñ#äí!»žS7(ViÍÖ4A†­V ”4lÅi5¼ÄG Õ`RBAR–…-{¤ùPêiÍ ¼„’W|=¼|%å¹×|-¿OëBX¸Ò:¬í³[È©•‰³øˆJzØÀ„ׇT€X3€Ø%»X–J‹*"‹ÃU3À[@×pÌb¢.‚È>øþÁ'ÙWt$)ê⪽×D¡%³ 0úW¦Óž†!»<7…::´«3VZÍUi ‘6¥MZžÉ#p° ZmJ; ×G¹-žaÄ¥mJÕQˆa¤RÕ§õ<Õr͇d =„"ÈtâÓ=ò9G¬Ùºj0;²1>Ü=( +%`ÊìZY©tV‚b‡¤°ÂWxÅÚ!¦[gù Л”pÄ‹$ÙìÉéJ¡Ñ¸º\´Eœk&•.f€Úž].Œ*ŸAstZ[B]š£3×@«,}ÆÏ…\ØÀ±W¯Ë¥´mÃß5=ÁѬߥV¸5C© °‘듃ZèâRr‚+Lþ2(-SÕRZ¼½¦ã•"ua·ñÈÓãÕ¬ôª)ïI8û‚;PÍZ5S:È1!±ÚVzšß;œç@3üVàª_Ç5Mg¸Ü˜[â(«0[ŽqÄ: ^èmÝä >qû¿ETÚTê©eê^éc¨Ã:ßdMÆ–ƒŸYX¥,a>aNa¥ÜIóI ÖÞ´C&îPa®a¾áæ[ÏêÄö 9*T½¼ËÏd̸ÍÍìË·c4Nc5Æ×âé3ç«0rƒ¯Äa–4:VI ¾cšÌc=>þ>ž¼ Š‚p””b'>dÆÜ '¶âÎLLEfd+†ä-Þ I†LIìÙbÞ :‚­Yã™=ÚPå|%1õ4å2Fe…Tep@åte"8Úî‡Oæ’tí]& •OñÁWÝeœfaþÑøåà,fZfbff]žOd6š^væ^ÞaÕ^Îæ£!€îhZ”Àƒïâ¯øÔ`-gH­€JcÁÓ[•TJí‘2G5gwN=Ñ`å7Örngdå}ÖS~•4Å€gõ^z \S~ŽQ\šî@Ö0…U­Ò3¹O å)ih)Ýæ`­h)ÝÑ`µæû©g5•þfv’{.h—hˆÞ \¨×ˆÕ[“ÞÔwÖÐx>NÔŸNÔXÑèîg >ê]­RR^ç8*¡þinfXŸÞ4 ÚÚŸ›eE ×aV1P¥Dš’˜þ”¯Q¤Fi6Xi =k“ÎUènš+n¥Ó#ËgEV@µ¡ÃIœ€Ëh™¶Ûi‰û”ah€ÄÎßõ‚¥F ưQ‰¸­ªî¢8ìÄ^lþ;¢ì•ù[‡ÑgÃ.íÃvŠ9ì-šX êÒFlÃn!Ûꣀx6¼X2IB†ÄÆÄæ°àÓ PkïØ¾0ÚëpÈO¢€Þ®€ß¦€Åþݧ]ÛÑ€ë`’íÂ~aÅæküPn©¾nHìXl«¦íC€£5µ‘ (Õ”çíî‘è2›u¢þ€š8¹ûPû¶nXìÁnm]ï6tV4=ñoèÆîKˆïB ï[PëwÕ~oHˆoÚ¾‚8s3LyVmkÁn.\š~$Ñå6d1Ç詚8> ì`ð `€Àðé`‹tÄ þÙ¦p['¿‚¨&kèŽ ëÅŽ$ûÍǺ­§Á–çGÔØæìÍnîØžqÙ.mt¾ëù—®XÃçlÞ¨1w ¯pí‰Æ€Íîl%ÐlÈlÅnnèîì 7íþ.'ìþSìÖìèNl çò:ïlÐsÛfƒ)_Š-t.×ì-tÙ6€×Eq'v¿væöí#_öj€Ë6w7×÷™|·p}×÷ƒ–®Ð%‚®þöè¾]×Oþxt¯qjgAßqçò EqŒÞ òÐþ¶óðo’ø£Aì\`gn]q9î»vœŸñ¯òqOzž÷w—tO'n—ö„rR'÷ßùÖþk ÃoŸ’$wF×wªïu‰oì>u=©‰uö> ¹–pÕußs÷–ñ…·x`wn£ïw”çy”ß4‚_Õ–ñ¾·øÀxƒþnF§ðWp ïst÷ûÉ¿m/h[–èø)éí›wt]÷w“üfOú­Ï“É‘‰u1ßP}™‰lXé¤G›øVp„'}²gî€?“O|Ù×}ŸzÑGvo\ïýi'ú< }#þÈù¥þÇ~çFvñNoÀׯsÀwóí—ó:OvAOlÀz˜‡ì1I”È^”íøvσåæqï·z’?ìúïíÞö~ïçù]·ÿèvmhLN&.i²ÝÙˆàq 1Õ( ¡ÆLŽÕIBÌalCO§B\.†"x,.‘†¨èBR¤â‹±R?[ëê2¥.årôšær³Q:,p½‘õ{µ®-ò@7*IÑÜKÕÞFÖÁJK!¢–d[ž¡€ “ÀQSghAå”WÓ"Ûjeˆá#¡UYhè[&î×ZBä–^èðä"IŠUŠÞ i%åé.`#u¯þX!+ž5h'q‘œ‘¡§SÕS3ë…p÷zw]Eàµ.1Z´>Û§À€œtIzû7­ » |L8(€mîÔ1ú—#±¤‰ÓVPXB\°[r± ¸%¤®Œa³©HNœ$‚CÐ ÛK:+䥱åKqæÜ5¡Ep˜¸‹½~Uúdrb;¡Ô9†@Ë£BýlâµÜ°[Q¤2 ’t\×Ê”Új½A'­:Å­ÜŸöN~%yé$YIÛH|!‘«¨£ˆËf’kØ›0rdýRùÕQ·€ÝJ^É%kÊrNÛ2¾4„iÙ“€‹ºã[VKÉn9-é‹R¶h²°±mþb›öPÊîvû;ôv·Ú`AõF.²!´R ÚvtâPTëmäÌø9éÊdÿí–XrvøÙà ôkµ¡ÞC7 ã>F»LÜ’/˜y²i¶á$+Ø ‚ "ˆ‚ :xà X „>x „ "ha‚ ^á†28b… ^Xbˆ~"‡$Bhb‹,>H!Š/rˆa‡2røÆ'ø!GÅÒ‰£Ešxdˆ1)cƒ1føbþ%’12i!–W–èÞTJé ‹VZ9a—M¢ø¤†NR‰ wãýxD\ÔòŒAs1O%xþ0ÌžÑPƒ§œŒù‰çøÔh>y*J ŠRþÃ1ê‰(§Lz…ZjŸÒäÓ螨 7•XEI“i¨šÆÊfåâêª<½+­µ6ëb¶ê «›µ¦²ë¬‰quÞÄ Uu:7ÖS~ùõ’l›ª©¡-«¬´%™°¤Ê÷Ò´ÕÊ-·Ï¢®²Þ–«,xÎ×M¶©‡_¸…f«Üo¹‘f쩾ì¨é5÷ ¿|°ÁÖÕŠ0Ã\Òp€¥ °Â¥ý /ŵ¢+'üz¶IÃëK-9þ<µ…¼2Ë-»ürËÈA|rWBùh2Tû\Í=S‹.Î×Nd003¬^qa'”ÑM;ý4ÔO‡´¾¥²ÕN®TÉ·iVÄD 3×núSÒ×e›}öÙ_Tr¥5°Íd­ÍqÜÀ ‡6ØaûvÞ}ûý7̶‰w5zKþ.·S÷jà;þ8ä xiúIüÒnÏ;Vä{þ9è/ß*7BŠY¼¹Õÿú:뭻κá–+Þ#r¬Ù]úë¹ë¾;àçÑ=á™^3ïÅ<Ô(kÛcÿŽ9ãÈK?=õ‹}yéÖ&>–©Õ{ÿ=õ“.þï½>úé¿|bå+M›úñËüø¸ENã;exmh-2.9.0/misc/mafe/help/mafe_start.gif0000644000170700017070000017301713201227060017426 0ustar valdisvaldisGIF87aZ÷d‚´,BdDbŒ¼ÂÌŒ¢Ä\f|,F|ŒŠŒLr¬4VŒÜâì\”žÔ ”ž¬Œ’¤t~”ÔÚܤ¢¤|†œÔÖØDRl,6\4Jt´ºÄ”š¬ÔÖì¼ÆÜ\fŒdz¤lTr¬¤¶äÔÚ줦´<:DDR|L^„\~Ä|šÔtŽÌ<^”D^¤ŒšÄd~ļ¾Ìd†¼,Fl¼ÆÔ\j„DZ€Lf¬\z³Œ¦Ì„žÄd4J}„ޤTv¤Df¬|–Ä„–ÏôöùTf’ÄÎÜTv»l†ÄLfŒ”¦Ä¤¶ÜDVt4Nt,J|\z¤LnœDFD4ZœLn´d†Äœ¦´tŠÌ4Ft4RŒùM.‰}“€‘ $Ùdwu$YGwTViå•TN e–Nv d’¹&Bú¸ã8îØ#gªé"Œ/¾)g‹&–8¢ˆßx'‡†!‡â`!„&è ƒ‡Xà‚ŠÈèüíiÝÕw˜¥ßÀ×Þ¦áÅGžyã÷ÍvßüóM'*Èö%ÔPGþ;‘±Ü¬Í-ò\M´æjë­ºÒêWpâ‚o²aì±È"{Ío±ôPB0ߣ€ØÐM'ÊX -ÙnËÊ?Ûn ­Έ«m¹ãÞãOºëjKA»¼;®¼Ú6¢Í¸¤¯¾Úæ»/¾rŒ;‹h;°Àü‚À k;„/ã>\°¦ø2qÅ㚂¸|ÈñÇÚ*²"»Œ&|²É(k»²Ë-[ÐM>ãZ‘EÍ7kk3ÎãF“³ÏüüL3àÝ̸C#M´¶gÔ2nÓãã´¶ÁmA0ãf­õÖ\g]uÔS[5ÓaŸq´¶I£}6ÐBÿì3Ï:ÿ¼³¶ÝÈóËà­÷þÝ*\rÈ#wü1Çk[ñűË[0KÃŽC~°ÁSŽð¿ýòk¿™Û¼ôÆ :¼ê²;.ºçškªCñí¶Ê|cÁµüÊ?ļP-6¶¶H²À»¬ïÁ?ü_¿l&×@)ð…o¿/°€' œ=?'pÏ}/Þ,âWu¬Š¾äÊ:x±~.cP“Ë:ðkC.ó¤Aÿ:°¤1?þ Øß8?¼àÖ8 ýˆ@æ‚ô»oP‚ÿQ0¼ ýˆQÁùqp~ë 80˜ xŒ~&ÜŸØñ?!¼¢…ø_ò!CÒ/4œ2²€Áuì°‡þÈðÀÿâ!Äù©¢ˆë8b•H¿7Ô¢‡Fx"ýÐ ŒÿeC XGÐP‹ýÁà^ãü¾¸?`‰~Ù8c.Òx¿l€ÂŠoœ_êð¿&Ì Žw¤_ ²8?ì/-ø£ ÿ7ÈB‚ÜãþšÀÇu0r‘åCã%iE:¢ñHó3cŸ2ŽQŒk”Âgƒ*ޱŠëXG¡øD#"Q‰®\¢oˆÄê‡7Œ!qXÃΰ…/œß A(ÂT–ð„%”1‘ùÁ V0‚ÏÌ…¥™¾:‚¼æ ö÷šƒ€üëû÷¿ü•Sÿ‹_.ž±.hc¹¨C9HÇ!œWEþÀö´×½~~/|:¹F>¯—½íùóà³®‘ ‚òÓ ÜChøþÒŽƒG Tð4NÀQŽÆ!'¨G/À·,ßôàÈxEš°Žôƒ¥M˜‡ý0(ÓýÉ´‡Ãðý¡ÓöÔ? à…*Í •„ìá ÒçÁæâƒóB öpì/ò ê…™Ua¾B…Á\‡l˜‹xÄ0—C´¡³°?[&q–¹xÃ,ß B#À5Š©Te§(Å\D±€„A þÇÅ0öÐŒ‡ådI¸ØÿãŒn„£1çˆÇÿ ‘~ü` ÉYBzV=$f¥¢\P–~s\äûÖY4–o~eþ-&רLÎö‹¬l ëEaô6¯xM¥]ë:W&Òƒr".}˜¶6w~fâYÅJV‚P]ëV×QÕÿa•ªSjCèT¨RS©ÌàQ­‰À´—›?í)Oÿ÷tÒ¯¾çt$ÿŠaÚuÌà vÌ2òÑ»…rãzí(H?:Ò^L ¤×8p‚|ôÁt‰°C) Òz„Ô%ÅAü²ˆ†f£üˆCŠSìa’: ÕhÁ€§ÁRs¤¢ €hÂ'¨‘"=ÎÆ'^ä1¹Çú8r6ôá‹"7¹Çc(A åÏ£ÊÙ8€<¦ .Ù]î±9ØñåÙfîñþ Òœ k´"È]x³šåœÐù2<òÜcxCÏîs ³áç þF¢Ýã0(ºÑÎFêäKPºÇo q6šp E7!–®4k1=êl¼¡Ô§rª{œn ¦nA ëÓzÖŸî1rÝc^ù×ÀrN°é;"ØÈîuѰW“Áãèñ°k[cšÚ«6u©ñQ“á¨.õ%P]‡OsÚÓ ¾tº+­nGÙÝ=ÞG¤åÍèl(Ñ‚´¾óÝg>g£ þ¶sÞã8œÎ]`3šÏÌæ19ÌÙ0Ç–{|ˆk9ÈWž2–£ìäŽ#YÉIòþEdYëÈ9ÖG²áHdìà÷ŒE‰­×Ñ«ØÃqH(òª=NÈÂç>†‡= â€áÄ'àÄŠ•^8ˆt⣋E3é“ÃFI:ù“hp’½x’«‘#Io  DÉG· .Ù’,y‘€ ‘™ ÐP$` @»À~'´’gÉZG9iG‘I‹ — I‹B i—h@öxý¸—üˆòHè´˜ŽèØŽ†ÙåŽÍðè˜'éÝŽó`hP™Ñ˜™Ì¸Œh ŒÈ¸dà€Œ®Œ¾HšÂH‹»H‹¶X‹h /ЊÙnˆ pй+¾aÕ‡臽àtA@R»9lÜósˆ( ‡(œÄ)sö‡'ÀLpˆ”Øt½p _GSþ÷ˆÐ°õŠÔÉu˜pP7>05z °dD–ž=¶¦¼PmÙàšArWŸJ O– ó°Ÿú‰qX–q=ö— d: j ù0p ªfZgà ™g¡„†¡Äào…ÖcÄP Aö¡A¦ oÿdBp¢=&‘Æ¢(iÈiñ •F£(ù–Ù–¡Öc—°Fx Üð ·À ܰÞ' Ü`žp@ÌPöPu ø Ap=v} 0khˆ/p}‰ÐRé•éI“$ž=ö )°¤žàž P» •½Àlê¦î‰/  ™ Ç Ù° Ÿö¤þQš EРꀀsZUz ·€m- * =Öd°¤PJM0l @Pj ½`'@ly ™ žp’l‰’ê¯ £-:«ï¦¢öf«$:¢%š "Êo„6h{¦gzÃ:¬j Ô‘ÄJ¡=f š ú¬j* üYG¹dûÙŸAöŸ÷ù­ó¹žóŸìÙòÙžéÉÖÀ[º `ÔstÝó›€Rãù`:ñ;¥uý$R²PÇØéˆub~ L t½PA€ q0ˆ¾1bF營H² ž'0°ÆÑ©¯vpøéZ ëÉŸÐçÊ °²ŸPþ+k².˲1Ëú /[³7k³+;¯ð²<û²• ´´ù@´/{ð²æ´+»´JË´ à´M+ O«´µð²ð J«µM˵Qû /K `»²ð€ X[X;i»¶+«jÛ¶oËû·"/;·/+tÛ/k,E)ðE Kk áðÇP–µPÇ@ƒ'ÀPÀÀ)°iÊêÀ·EÐE@Ä` 4P“dj,²/¥BÉh`§ˆ«¸' 8¹8’»ð±»¸ûÀ½²@L0 ]À· иA@$€»RiuÐ'``¹+«Ùþ ’Ó{¹€ÛÐ ^‰“$Ù¸+P±ÀÓ‹+ ¾øÐsŠ·+ ¿r»/«vÛ¶÷Ëð·û‹µ p¶X;¶ @ ^k\ÀLÀJKµM{µM µRµ<ÁG›F»²óP´¬Á ´;Û³ Â4;³8»²ú/Û²)<³*\mð™®#»ž—‰s؃=@ u¨Üsˆ>Ì 2À°;QÅ’uIœ9Ç ˜À°Í)PóÊœ°ˆØ { ¶/¶NÜ=Iüsõà°›Û,M bÀv*eì)Ã.ܯ;®õŸÕ‡¶FÇÕ& \eylkóð |ìÇþÕf€­*­gvÆʬu¡70¡j6¬v ¬¶–µûFh» %Ê ¶¶œÜc `«.º¢´Úc1d§Ücd°š­––­­¬Ê¥¦ ™À `Ðö`˸ `jáP 'Ps*§·`í P‹  Ðsjmö`ÞаРç`cZ¦QºÍ›+ŸoÀÍpö¦‡JÎöÇßÎ㜠ÈÁ€ Ġ銸‹Ì‹»¶ð¹°ö°oð²&öÀûÜÏð0ª0 £Jν`λЕP ÀÀ¤7 A`Ð&ðÊ<úÙ«¨,«/:Ò¤Œ¢**·ŸŒþÒ0à¡—|ɦ¿Ÿœ¡p6¬Í È7ÀÈŒìÈm†ÈmfÈ jkÖÈ,Ô}ÌÇzŒÇxlÇ  Ôtœž ÆóÙé:réeŸð MP Äa~˜t ÖL@Åõ ÆvtYÇ #•sqð¯AðÅ F¼y°†Ø ÓI‰ãiÖ~1bÈSÛbœˆ{D Õ òŠÙ€ (‹íÉš1\‹óéž­¸‹¹ˆ\ð—mš}”6à ¹˜ 6P¡=Ú¥]´°Ò\€Úµ8(€‹—)±ýŒùðŒàˆŽ9™¹Í˜ÚXÓ… ¢µH¬¬I 'J‹ÄM‘Ä`'‰ µ‹´™‹}þ™x x©—y‰—u¹ ‘að ¬ Þk)Þ’f‘i¨$)M A PUê•/i¥‹,‘@ 'ùQp’E`>P>À »`ºF“DÙáK ¬˜Áœ9yM¹©ö ΓP¹EY@ ­X>§¸ûá¥íW‘p° ¸Èâ “ô¾$ ¸ áö—“ðð 9‰ 0Ž2Þ¬:—©Ý×=äþXäG™Í Ïݘ­xÜÆ­ÜÆ]Ü´°¬PgЖÖÐŽÞ‘’Žy”ÈÚ–Â}”i™ÐȌҘ ï ¡ý¨­Ú¬ Ã@ÚžMç¢ ÚžÝÙhÀÙþ› ÚÙPÐdU¬©¨ÍvNØ0g¿RPŒ°’Ø'Íù;v?Œœ_|aâóˆFÜ œ`ŢΈ•ÞœÚ <áÄN7t¦Æ¿‹¯`W ð 3 ¼pM °À_».ŰëM /M0 Ú ìZhì¹x»> p÷ì¼`ZÍ>í»þ¼€מí»n ìóDBåÐe— å0íTN%U$Äîäî¹ N…]$Dïe—¯ÀìÄð ÂþCe7z¹þž ý.D»ŽE” OB AC°ðOBCÐJ¹ð~õDeEe¯ñF $þ å&§ €»ª€»OÚ$ÀãœrZEðDI”&ð»Ní2n`,°¼cj¨^ ›ZôÌî ö ¼0¯©!.§ÞPÊ›ã¼ë0@Š` MÀìåœòç\Îù¬7OÖ€A Pö@ö7oÜ ð ®F8 §›ÚÐ]é Ð M™Çà•8P »òßñ?ñ/ñ ÿð _D €R íoð¦5ðuøñ?´ëßï1Tv[ïb ñ˜Wï%p_úe‡ ÷îN¥îâŽîæNîäíà^”í¹ÏíÕNíÃ`í¹íÌîìÍî^» ÚÀìðí¦ ÆþŸ À.ìÀ ÏPë9Lu àt 6R‹ûÖ–^žÇá×!Åu#U °e]t€éÀéQ‹›×¿;ÆþüðÕM°ðoé_ `0 tP¡Ë×´uÓÌQ#hÐË´ý\‡+ͺ-Ó$´–¦â4k^6Zë‡1dÁ N»‘¦a ¾¶4ì"§ÅLx/Z¬k¡ÀΜàxæ7³P¡Dgæ‘WÒ™ëò°[¹&ßÉ0bn¶ˆ—çº0®"ë@q݈·¨&4^Ú™kÕÖª îL]l[©±u\œhþéMÛ÷ÏUuÖ=+²`׺"ÐHHiL‚™½k!Šñ“+ñ®Z½¸þxAD[‹'ê˜m¬ˆ¡rЊ¨U$—I¬‹bÛìºDE®ÈTÄ€fh»4+NAKpY-¦x·ÁÞ„][fL#n¼ñ.lÛ+R@[f³uß@܆Šðf¯‰o›q>Î$ñY'ƒùj8i•ÀZð‹'#þjÁ¸æjA.¡.Э›âñ`%#² Ê*œ²Úª«•tá°¡0’Â)Œ~ '!ð`q+¢\ôé&£zâiŸxªé*Žhá¥<j膊4 I‘0ò¨ Œ>¢æ#ZÈÅ j jᆅ:†„H¥ŽièP¥‡XÈ àš"ø©ç„61 ¢ž83èþ…No®9SM6ãp3ˆ809&:í¼†ŒXô¬§—8êÁäLâ8¦:{™`CÉ€KÕì%Ñ7=aÐ:½YäÌXzâU^˜á›„€ÃÕ:ˆ)ÆÕoÌA¥Õn¨µŽ€èGVÒ°•j|ýÆX_ëP ؘuö›fuE†[È¡ÕoÉ¡Žoêˆ'•o¿‰§ÛoU ö›o†H÷#^P×]xÕ}7^æu]a`ÇÖ7JhµŽlä¼ø[G×lò‰· …Õ•8≿¹àâ VwãqiÉa²ø8äoGl-¢f°š`.®˜ì‰Å÷`hy—^þ¤"‚ˆ†^ìyy0)êXÍþÃÁžDzÀ&8ø†¤±n*ì!`¹Xxvy†–IàåæX–[B|ޱ§ö@õYšw1»¼cÞE  ñ;&fXGÝW:pr3΂,˜VÆ•mF%<NÈ#Çbxpn|ä,0·¶Ý°t5 {§Ä.¶±EìïšXÇv»Úo=lµ‹íl¿5SÌ@w &oþ0cÝívw¼Got÷@bhÅyiÝŠn¸|¸‚—óá{9¿(.øP€,à! áPÆ,Ž$œâïÆ/,+ˆç; ÑXy/° GƒÏÇTЊ,¤|å^F~j°<åÚ`y.  ´æùÈ:ŠÑ  £ƒù(î¦[[tð¼¸èÊ•Þó©·–6Ò[ÜsÀÉÀ/pœl”`ìe?»Ù³Ð ´¯=ì-Ï‚Jô|X`î-·8à^ p˜×dC>š<˜vðC-Ü¡ÞÜ"]ÆoF‰½œÀçøˆ÷@à7Žt¤›—º@Çwè;ìa×þé¦=p%.q/¿˜ó?rçóÁßâv@Æ­pxmkOyÆ÷Ýñ¾PïákûwõʸÌb°€/<ÞŒEçøbºÜÓ>}·ìjÏGØ;olä øXÇÆ ~†4 ½H…Ãñpj¨êÅ h?vÐrtôèzÏÑá…û££ü-§¹–뀘›¹Ÿ :j˜?—k˲‚ÔB:Š“¸°{@eP¯ „2Š ½‹›8eð¸e(€|p¸Œ®p¸õêeP?S Ö³‚“Cº@·d†v›t»Á¬Á ¸Azs7¤·v!uS7f B ÄAtBD·LI'„Â(”ÂÀ*”þB0xyØyȃ0Àƒ/ C1Ã2Ã/$Ã3DC@y(Ã6\Ã4„C2¤Ã/tÃ:$C6ÔC=ÄÃ/ÜÃ?D@”6<Ã>$CpˆÃ@dCC,C9tÃGTÄH”ÄIÄ>DD,ÄKlÅ5LÅ:¼³P”ÅQ´CXlD[DJ¤DHôÄ[¤ÅSìÃID^ÝÓ<õS@Ô?%T?5ÔAÐ>MÔBETFuÔC]TH•TCT ­ÔËHÓ5uSÏdˆÏìôÔ íÎ*ýÏ*íR-mÏõÌNÏ ÕêüTåÐQÒÚôÔVõÒÝdO7½ÍýœÑç|N*¥MÕÒ)ÝÔdUïÌO^]VU…ÕPEÍÀ´Á¬V¿¬Vk½ÖmíÌÆ”ÈTnÕVoíÖÄLLpMÉìVu5×ÏlWwLÃWÕôÏÕ”SÈÕ|Í×%þeÑXõWQO ý×PX€5Ø‚-XER„]V…eØu؃mR\U~eR‹µX½KºDÌlíØo•ØeµÑ‘åM׌UXõUïÔÕV…Vƒ-Q”UV— ÎWÅÑ×<Ù–]Y‰}XÅÕ›ÝÔœ5Y”}Õ åY‘ÍNí„VLUNòVº ÐLmÚ¨EÍKùÚ«ÅZ§E×â¬×Ú¼W¦Ïè<ÑmN²N×ÛÔL[êdÕ— Û³]εuN¢}N°ÍÚØ4M×hŒç¤Ú¥EZÙŒY–-Ï£•YðÜåÌY•UÜÄ}Y]ýÎÆ\»•ZºÜš Zät[ÌÝNÄ-QßôK/½Õâ\RÐRþÐ P ý\ERÒe]Õ]ϾUZ=Y/eØ¢ZQ=]z×¼×ÔĺüÝ™=YRÑ]ØÕuUŠU^âÝÕâ-^Š ØÙ\UÍUW}ØMæ]R‚åÞäØîXhíÞñ¥^iÝX½•Õ(¥Óà¬U)åÑÅÜé¤\÷uÜ]Íà…üµ_î|\]•[¥Ù£Å^æMXãÍQç=\á|ÜþåÑçm[ìÅÞýMQÙ…Ú‘u\ÂÕܹ|Zô•Îò$NÞàË ÚÖ àÊàŸÜõÍ®ÐE˜ËßÍhOýõ[£]àÕ€ÀMÿ¬Í¦Y£eá™UàØÔÇ»ZéEZÞÜ v[#öþZ«å`Vb­]MÆ_[Íß÷Íâ-ÖM³Õ_ ÅâÓü],–[2ÞâßR4æâ5ÆÐ+^ãàÅ_8ö]ݤa'æP5Þ%ý]ýÅc1f]7þâc?FM7ncBæb¥}Öd½Ý¡…ÝÆ`YÁ _FžZ|u˜!Ù¿…\îœN”ÍÝ×äa0Ý`ºÌáVÛídæZh0e‘­KÿôaVÞdãÜ]g­Ùbeeý¬åF^ä·NSþ×V&ÙËåق;„ÚøŒaã]_cD^ã7vß,]j¶_³ec:žcg.ä.ÖæäQ+þænÞænäg¶Ø=ÎbuVçh~N³ çq&ävæQ?äqþÆß2uå¶NÜ|dIN`þuSÆT VÜ—mÛin^Ö|Z5fa9uáU–áŽZ †Y^-eïTã7ÝÔX†Ù“]`öfûÕßõæV®ã{Fb à¾á‰Vh ÎZ L…bP†ÓÓìÛäTéhæã˜^p6gi–c.®c£&g@äl†æu^jMiyvân>ävÎc¨žc{jå¤áj&g§þêiÝÛ˜UÝ(…M aL¶àQMÑ?Öi@ݽ­âræâCÞÑgÆj¥gÆiŠîÝWîá9~ftÞß{.^—v϶&åûôèyVàZvê;v_z†ìºŒgnÖêzvç\êÑ¥UªöãþCmkì…FfôUæ®õTÆëžææ0ê-êÌŽí‘fÎsFê¦vç£fjkÎê°j7¾æØ.jÉöR9æíÚnjzÞmÁöm°–RÌíSÖçΔ¶îSfea¶ßd Ó2KCPC0h(o >Ñ’&èÆ°nëÆf²nà>j4nh®æ{åPS–á&ÑìfåBX€Š„Oþ>MënÖRŽe|ð¹ôoŽÞÐë^æí–aP–p®.ägðFi'e7ð¿n´Íâ qý†i¿îWñ÷o ÷ÚÏå`œnìOÖíxëŸNjŸ^êŸfçßþj,Æq̶kimÇŽíô–gq–þo¡>ã§Vn-®kçTòžVìàNM¥åhÔ4eø\ã†ÒÚ~dhPE8MñFQܦr´¶dEæî Ç7§m¤Æß ßjÔünÝÏ"Xß SeGO8eñÆnçó-÷óÀ>ðÔäáA·oïl?Fl%¦sDWqÄ–åFßï×í\.ôíôÅõ-—å@×ïOçaä¾rù¨ÚÆÀîö®×Q&ê%‡æ®.[àîôµqénî^¯u×k©Žg¯g%ö—ç²öõÖ~rø®óãžã2Ío÷|S.lØ”cïžWL5„V=ïNWjÕ\o“6O mt\çuºDl¯vêde¿ï¾…ì]þ–å,uL·÷z÷hýÆáêÌOBçlEŸOS6÷eÈ®öÛ¤áö<ñUžÏÅîs/%uïT­&ñÊÖï?øXvpYþω'Ñ@~qLfsX7O>¥è'Ïæø&i¤fÑžVõc7v_‡îg·õ¼>s¡æñwr¼Îù¶žm _ygî™ÿù£oò½ éìé!ÏrlÎÝÏ%óجz'v+sRfO€¿Í!—sü”êÓ¤Sâ…SÔÝà“Öò@·OýŽQ¯ŸpX7wPNí®éÊfpæy—xâ–ÍìÎð@¯ûJ¯W“ïóʦáCoïÀÖðƒwM€eS·nNÍÓÆT ]ü •uá¶ñþ_/vZ?öåöñËVhu&[nÎz÷yÑs£Ÿù:{göÓv£òÂ{}†x®xŠœvì~u4^oóosò.óñ&þó&oä×Ú ÎrO õz}uõ?GôZ®~ì÷áú†÷iEyY.xÍøü&q|ô÷N¾ïsrWÿݧðþÔÏRÏrÀþzòßeµg|8íøï§w“@+-‘AhÉL!Dh .d¸€áÃ…'fäX`A„ñA,b²àÉ„'D°(bA’ ¡ÉŒ9³&Í„8sŽœ)ÒçM 5òÔitfσI—µ‰ÔéO¢Jƒ2Z'ÂMIâÔþj5g×¢î”I©W¯'®l»‘¡Äß6”‹ÁÔÐRô° ¡‚|  X‘àÀÉ\æ-²ñoÁ…l„+°®e¹s5RÆ(‘àÝ„3B+ÀO‹”+ÖUèy³k×p%rŽ=·.H¸A^œÜ1"K¹“mÖ$8û²ïÏ·ãRvͺam–g}_^®dæqÿ²d{Ü)x”ö—&¯´öÃD¡såšð,Ñö=åïéÞfÔ¦[ Š k?<€ñÍgThý7 ²‡ €fõÞþ=Ø ƒL݆6ö˜JÜA“[n¤Ðz)ýÕ—!=¤Ø^~í¥b„TbÜ‘6œ\þ!Dg“å¶‘qª=Ç£K9y‘ixé¶’l×­ä“Qb6‘Gª=y“yÈd\Rf¹HK]$kL>Ùåhn5™Ùea6õå™frÙ$sY~ÔiM‰”ŒIä­dERáU–5¡~"*a‚•„51š¨ƒ“jeé áªç~&ˆU¦úAêè§Aíd"\;zÖV›V>dÜŒ‹lXØ_1&Ó—".*XaР˜«‹‹àUš=#ŠÆP"V¶IÛ‡ÌÂ:\²Õu Ñ]*VGR’ ý•'LÝNµ­hAF³ÜŠ ‘¶ÍbÈ#L{ÂÄîWàF”^dõÊ{£½çûNɤ{.¹øZ•çþ«£û”TEŒ‡y¬º¥S……)SRJ(T¡Â‡ñ‚K‰$Õ¢!gèU†¤^(j¨wj§ô=HÒÆˆîwè¡úXY³y˜m‹E\Þ‹6˜a›QŒóÒ8bFc®r³¡·j˜¬u—°ä"‡Rµ“Æ®HUpÓõ~¤/CØ=¶ÙõV¯Aé’æ0“¼··n’ûÔÞt_6Þ 7ûàøÊ›ï…$5ægÃ~Ø5Çáú•|C%éQN¾)€^®)P¥v>êÄUQ^”æb…¼9§I•^èçõ™î•ਞ»êqÃY]]×'õÙï´þNZ¯¾êZXïäiYÙι—ûþü’¶ÑöÏ?fPÂŽ “Àƒ«â¼ÇÅ®øÉp[>Àâf¾ÞÜïûþúêǯùôÓÿWû3ÝX¾ùÝÏË÷ü<…=…!d<†;˜Ïd‡‘ÎP™œ~873ŽLeÌÌè@ŠÁNQ¡›à@f±”!E>gIœ‘€Æª.EK`šž@x”5 ù…/¹‚ˆ ÷R<=Ć´šáIG'5ʼnLÓ’SuÚB¤ˆ)Ž9IRú¶··n«ŠúkÛö¤X²¶…‹oî[€¿šÆÿ‘)Yœ"2Æ1"D‹fs£ûê5¹HgO cÜ]ò¨Ç=¾„el]Å>ðìdr¤VéA”=þ0r ›ÔA¨ºý¸lA˜{R,GÇÙ=E-Ê‹H¯H/ȨZÃÒËáîÅE÷=$ySÄßßÇÅÒò\‚‚KJs—>ñ²—¾ü%0ƒ)Ìa³˜Æ<&2“©Ìe2“— Óå]„%M—PSXÃÊ ‚¬‚Í-bÎeìd6=7H ‰³» £.I s¢N›_!Ù¤Þ N¾ŒR±Ë˜†€7íè+BMÀ\™ÊUJÅ]*J^Á"·³µ|äÃßôæ3pmOh&F}9žŒ2s<½ãF9šÌz4¤"=©I>J.ƒÂO€&à #H¨HvО¤j †0WSœÊ¦1mY;E'¹¡ªlþ‘ãÜ"7Ȱ–N1”sû[B¥—›B$?^ü ?é¿ýÕï|¢!ÍXο¿„&5¹üåFI R…•”­kU+\í!W¹¾µ®jí\íúÖ¼’t®~õ«]K:W·Òµ°må«a {ØÅ¤‡Ýkcïš>Á«@Ù”`Q™Ôv´B&t "{ u’ª³—¤h%æS Ƴ›òç©j“ ¡ñ€±¼á\©”1 Ra͉@kÛEá¾²¸»¥¿*êÅå2·¹Î}.t£+ÝéR·ºÖ½îáÄ ÊG¹Ôœ¤Óbªš^Jfé$ëV{ÔDnò¨Þu©<3›Ô?®Wœ “É©cÅ«êÏ\þ3ŠŸÌc:ûò-k6î·§Èý²&«‹ÁÇÔeˆÂSqê¹Âjá W8\µÌ‡õÖÝ’˜^ÆPˆSÜá³XÅ-^±‹-\?ƒyKf+Kí9ç[z’3›•“¤R1[ÎFÒ—sî9aä8«Y¤J0QŸp Sbáo·‹mÌjDüSIü.0úlÔ6U{:!BYSœÓLÿEñ¶ªt³¯HFÂy Î(gyÛ8¾¹ÏpžóŸý è.BF*àƒ”åNfßÞ6ÒÆ©koh7˱JÚW„“Fm¥yÓo“ïªMW<“©ÊÖ)5WMpÙuß} c€†Ô·z¨¦þN|½$—1Ðv.c÷ØüæáêY|éË×V}-èeûzÐÌv¶ýj,i–r/µ6!å)ZEŸ·Û,íiÏä1×7f·~õ«)Úv–÷´ìVŠIò8M=NÓš|”÷½FÍ=îûÞø¦w5iÔï€Û»ÞüxÁùmo€KSkž ‹ÛLliïyâ«ð~Ïû” gzÒ¾ô<æàGz4£¾ð„o=ëüæ„©ÁÌš–Êq>dÙéÌN³PúÒþ$U Íܲ#•îþ´»Ýó¬ÙvÛ\œ4z’ÃìÎІ9,„W¯¸ôãÍÒŒ¼.å{¦…Š}L²Wûªƒû8Á²Ïªs§(T·x©½Êê²åÝò=s%|ÝêjQ&»Þ=Oq\tº‡÷FVjlӑ픺iÚº Ï™—za_þéÜ¢eŽzÛK1Ú¸mPßaÒ>ž­õݬýݺ%ú‰qÙØþ‘˜ð­Œá}Ÿ£   ’7¹à a“†YÒÍ©œñ±`e<w… QQ^«YßT” ÎZ=!ÊôÕš_6ø‘OäÇÊ©×ßy`òAZ’©Ûáõ¥EUA’¦MèT•{Wñ…Ot_Î"!­5W¤5üÍ_(Qà¹¡ÐÆŽ¹-ž\R¼àò¢;Má HÞà1ˆ"îá"ºšP ® º–!"ÙÿÑ\¦!R"JÈ)ÒùUˆjÛ«µÉ Î79ȹµÚî\&"¡è,:Ò¹•á¾"/’ Ãq¨ý\íþÂDÎöià"Jþ‘5aÚØoQ!P5àþ”QibµÙœÏ} .c4†!Nf |ý˜6ªáºÍ‘"£:Öš*Š*`Ýßh]“=Y¶¥_ÇÀ#$‚b|)#hÝãÞÔf#4Æ` ÍžÌPžõ¤@âký¡>Rºå_EFÚô¤YÎe;òß#~á=C$.Nâž—ÝíœN$zMìQ <"ŸnŠ BˆÒ×Whn@¤1N¡§©`ò Ÿ1Ú¤xù‡¦¡€€ßF>¥Õ¢âG6%'‘Ó02dù¥N ¯}" m¥RKRëXâ,åÝå¡:¥P‘ÎBn¥R…w(X8=þ£ò à $Ýý ]ÄyÀʇ̆I:`†#BjC:ž,6㦭6ä*–¤õá&¦VH"¦?Ê×ó™eB¾}€#V~&1š¡&ñž=i#·ià©Í$^$#}×2eRŽæ¬ÕÄœÄ[ˆèˆ_Ðí$i¤¶¡çGJbAö¡99åBšÎVesž$IV…†f§]¸½¥P¨ä#âr^_tŽLw.ÒbÖÝçè”=n )"X–çAêbŽ}`v³¨Kç$ß5"#Ž$bÛøy+6äxRd=bD–ä-eö•ŒqâT(²ZhPháWÂW&Чk‰æ6M ‰¥ƒþ–+&’uŠ9a›E†äíÄÖX¥cbc9&牞›ŽÎˆ¼†–ÄPÊB( åÆ %&"æñ! e&©¦¦aßy:ãqŠçN%©þaæ‚eã…Ì9&ã7bhXÂá\^åx*H:&¢M.õàOU$Z¨»Q&)`ZMCüHrµÆr¤Mffs'‘ g:*i‚îe~Æf˜±)iÉd'¢¨FÂi¡çãÅSäämB*j<‚'=(yÞš:ùé|¡–u.Å‘€uº#RJ)® é§F)U|Ó,‡BÍ…ÓˆDwè),©%¯%–®*˜q¢‚š‹Vbq¢!Y’éþ¤rg£r庣VJ´^¡RÒ{J›‚#ã=Z{}¨Šeÿ‰©Øm§LreVnÖz–(¬Úf–¢ÖŒîâ¥ ë˜°Š‡ÇSá!œ¸EEèàŸ'âe*g²*O¥c˜º*’nd{j—¾©†+ag’&–šeÊ'=úß<¡hÛ‰Y<2({RhB}å¤gJ+N«³*È„ˆ¸¬ ÔÈÆo° –Œlô«Í¦*윅W2¬6Vá¸â"s"R>fÆëtrdl>f"lêÇ©’ãCNéÅtcuf¬tv½:N¾¦ —ì+›¨FÞ¬bäÞݶ>ë5Ž©dv-5#Æ®«ðVi×Rªà¶+…li°ºcð2!¦Ð¦§ÁwV©¬g>®é¢Âk̉­Dn¢Ø¾ Ü€ØÞ„^èadD¦¿)Én£:*P"¯.–]¢no ^Ûà:jJ^¦Ô"(ufcþçÑš¦ãÒÔü’*|PîþáxY¢P"°lIÅÖT-ôß &mï¢n“ lþý„øâ§ÅqUØ$ ÿ*–oî~륭ÊVÊ岊k³vãÀNk±6-¬"l©òo;2^~ºÜ=± ‹% ?lÎæ( GH‚Ôå­¦Áâpâžî%¦.#©Yý¼Þ‡uÕ¶pñýŒêšiíR)çn-ü¾èGFqI2­„>æÂ +b¾äy†ïvê¢6®ð žpêŸ2©^ŽÓK/?H莬öþ,»v㦠¥W˜‹±‘œÉÅ%¹f¥p*˜qáå-Îù¬$ÕÕÖh¹>§íÆäM=©» ­îë:©²Q~²¸2¬¾ëZ6ë™–×û¢00×¾*O`ï'lâ¶¢ÐÆT S[þæ›Z=rÖÖ­3¨å®î-%>g&÷íìvì°Þ¶1ÏžÖÞú-O:™£yi=ÍfyJZ&q媫.’h7 ñc窲}µh·þ+ËЇéjLŸa:7‘Üyf~˜í§¦—¨Žqç%Q®jêó÷ª1cúóúÑî^´yR… [ío6¡ò‚*F+4— ãrï.–âÿÒãéÉ¡”K¿4LÇ´LŸÔkb2|±¦rr›Zª¢îèÂ3(³q¤ú/UÖ²æÂäuRlŒ"u)'ðö²«à¡“*(ýp½ÄÐ_$ÉÁm5WwµW5X‡µX5Y—µYŸõW;Æ k²±vîþl@J5o;àZ?ë¹®5mF¥'cäö0çrsÔF­Š²³÷itJ/ºµ.±O=¶„uÂYe[Ód{õdg¶×‘5ÒYöÕmµgKöÔaöf—öÒu¶¿ýÛ. ï©Eÿ4ÁþGB_)\'ì|¾±U¬Î‚lôO®I*¬Ä.i ³‚ÒöCFÚÖè’¬ôs÷çÑËé‰˜áŒØ †Õê•æ=7ww7ç¡ïs7ußOw;·è]w r•u‹·t³w‰ÁÛIP°û>(Nsr:-²Žg¦¶¯,CaKÒò»Roœj¨ ãwQ‹Ù0Z!§‚Zã¯ÉÊ—âìþšôžÕz¸aþésI‘†SW‡G2†/ׇ‡xyXâÖ°Þ®º]óâ>.]3ÞÓ&m0kr„Js=¿¦…Fô;Ò":Câ·­³²‚h4+äkðL ¬÷¶uƆn"$Éí…+…™Ø1“t Æ0Ryï¹–£-³ oi9”£•o9†H¹˜G÷‰=ÑŸP/" +nÏ'ÄÖîTÿîð²õM~fzm´^26Bú6±Â¨Gcc'+7wô+·zâaiÌPÛV¯«ôMc8=ȤKׇñûÊLŸTè¥:¸ãö,clUÞ–ñmþÞØ£F.—朿vçþ÷?ôRkì‚ã,¼–úf d«oê0‡Êr;¹MìFþC¶Ëò“ÛÚ-Âk²ó3b­²÷¢­×‡+qì)¹Ll:ªºZ©«0¸±0@·°«èT2kM§,Îñá K+ðnç¯ò_ϵã#raas»MA8GÖæ {.G7±vTÝϨD`{ã Ø$D¬6»úo{Ÿ*üõK‰cºƒ7<Ѳ‰~ædÂò»s'Ó_GjkÛoÄZ_%›³ÆÖ‘B‚ïM›ÙÒœ„„.s£ªF€„=3x ë„Ï2g|SÓ=s/…²²¸3Œ~Q.ºw or¨siS{{(Ã&-û7¦x¯ËE­éè_àCu”áƒ~r’óÎǸˆšû)ß·OþmÈ÷²¢CѼÒêœÄ“È·äžeg,äžóÞûu,ß4ÀÎn2lTÛOsɆ¨5›¢Øf¨Íå®]{óeªr8÷'£ðiSØ+RÌÆ,+µ›þ=åþ2R"Ǧ®?™ºŽbfµh’<ÇÖìé`fFáŽ~ m;Â7n;rìÉK%ËsvVÛä,0~¯oâü›W|~ö~ ¬"+‹ X”Ìæ‚gš5 ô&O·ÜJ½1aX“±ÊLØå`¢Tùº”™5åaÃ1njQrcÇS©Ê,²™.dÆT…råÚ¸oTÂU•ZÎ\9éÖ¡A“DxuàÓ­# fMÛ5ÛŸ>ñÉý¹²ÐܳÅkν)7¯\œÎß '.é諊?W¿üù¶îÕªs;½>$á²Å³^º”-NˆiüŽ{îηtëâŽù˜õþSì™÷Ó 6Èôï¿– Cª¶×4° Ú¬ÿŠ2 ³´ÍÀÖ°**@ÙB³0°ó,Ä »û0C’ÎR.¹¸Úš«½dè{ëÅåj"/œnºÑ¬Ëòɨ‘0ÐDôT\1½l06OLÒ+¦T’q øÚƒ1.Û’Ï·þ¤ü·±À o"Þ`ãÍ»Ìü:Ð%žDÄ¿Ð[-™"ì™PÈØFl2µÿ’í?˜d3'‘^ªQ#DjQ3lШ â±>¶Ô‘,¸Þ⩬åhŠNHû>U.Ô"éoÒ©ÚLOI¦`kiÕ)T5RH%+­,û®D ¾ålRN®,‡6¼È*þD­VÙæänÙAû[­Ù?©õÊ LT±ó“°12Ut¨E“%3YË,0P?E;‘R0]ÃŽIr›v1犵 "¶î’É·OCm:7•ß­ToÍp‡T˜¿ÏT«p¼GOCµñÜm¸Úx Ü•®;@$`²œÒӞʋ2#.ôÕï$uÙÞ0±¥ŒIdi¹Î„¼ÝsJAf×å'·4QŒT;h {™h¤“šªéŠÓáî»ëäü¶†Ñ'bO6ùÇÎ0£–ãl¾ÙMŒq{Ù35c¥Ù2ö̾ÅòÊÈ®”ñëZj¨Ï×Z[Ž[ÃËœ•Ê[õSºIžðœðÙÆþÁCõé³gÕ3ÄË…*6Š£®<·GsS[Y°Pâ1SƒÖ2SOMÝ 'ß,Íò>^yu×Ñ©„jup·=45Í]R“¼h[e;¦„±$Ùäêúy5ÇÔÖMĶkjWîÍìo£Íûœû£~ç9Wh£S%ïè‹…ß ¥ï›.Úþ§Q'mí(ÝŒSþúñ%°º ‡uÁ’]€õáÐ'ÎÙÕ\Ü2‘úŽÊÚXËÆ÷¾\]/;e3dèw=‘xL3¾Bô|†2!yFE·qábJ„ž3Yo{eªá ãÆ8Ëql†$‹pF§>h.†—+âäpXAøõ bëҳΖD¾I?(tþ^¯6+BO…]\áa%µîHQŒmkšC'«HµkhÁŠÇТ–=¥P‹P|áßÄ$ÃD5펌 œYµ!¸¹FNðÚߕҷ§#ëcö X'Äqt¥"ü2fÁGù.ŠŠ3ž[ò‚·ìi”2 %)‡JSNåkØù µHBBêˆRÉa ×C+ æÏ†ñšQ„Lx<íT²^³T\U^(%0&KZS˜à޵4q‰.!Ë“"Ïw¿hΤsò²¤ÆäÌL~ðl¼ÄÙ"‰6/nbdÑb2Z OÖQzaƒ§<átʼnx Ÿaä ÇξìEÌ’l{åS6Ù Mëf¤³Rþ"຅a²D^É ¢Ž%£Ù˜„NfÞ ¢þD‡Ò&–x’Tܺ¹ÆöÕ²œDÄ£.BÇ®heOzÊóHTõ% ‡qÚGG*IL¢¦Y‘I3jЪ宋øU×4¤²Ð˜Å»–G)—¸Yj5¬6”fürZÒôih;<¢VáÊÔ®jÌ’àêfTix×ß™.<ªæA¨øÎ-Ní„@­âÓõMTÏwœTQbÈɶš~µ sµ`NàØ+ØG}]œüI¤™õMßä^HGkÑM¥#m«“zFÚ¤ò©}AÔàA+KQfòr“µÕñ'[÷ý¯AééNþW¿†Õ°ÜúÎÛt K©¶|Âdrm5·¦@3„´mší LÒ¤KªCæl'#ТzT™KmfÍàËÛ²¢‘·ÜZ!i!¢ª©¸LãMÙGÍëòU¤o¢ÜôÔÄ,¸‘$Ù‹QϘR[z•¿I“Û!½©Fo†sœô©oÅ<9¶†jx Š$ãú7 +«zä¬-_Ó³–{XågN¼Ä뺖·Ld$k5¸¦JrW¿÷Û]v÷ H%1f uÐ,uÛIòt—dñU¬< m™Ë]ö²ä™äÐN¸1»²›xUÓ@™š–™mºŽ ’y¸üŽ7 Uï4/Ä8Φդl•ï‘Ïþ+ѧšéí¯éÂl(‚ÎxÞ;§Wéj">–äÍö/:+*+[ì‚â\'K4‘/úËW-ò ã¬˜7‚ NM`tª¶€âe:ÂÚÑØ<½¹Zæqµ~J4{-,´û;± ù˜æHãUwñõ3xHmiO›ÚÕ¶öµ±mmo›Û_¦ì‚_ä2ÅWâ{öQ¿ùKÍ‚ª³õ!¡qX#v_X/J4³ÅlïßE—¾š\óg¬)¹s›ÃËölbµé?ŠŽ³÷Ã!q‰Oœâ·øÅ1žñ’6øÃ(w­è)4×wÊsÒªˆ×©…*F' –Ë·ÔÀPÆxÒ*ŨԺ þ±œ§:·5¤H¡yc=åÕ·fC6%E$à˸·¤Ê„öE—¨G]°UùÕ­žu¬K}ëZ÷:׿ö®Ë„êc{ÖŽÄñÞ¸d)ä)4Ô2Q"[Ôq$| v€L€ÂrŠ}ìÜÞöRg‚“¥³]ð~—·÷øøˆžïû=qò’yi!ï”´kÜŸÚãüçAïùÐ{ô )§›™ûbÑêQ_ÉÈ!.ãÁ”L™-©¯Ø¢ÅDÌÎ>¤ªšîUg^ÄëÆ¹õ¦üå)¸ÛQصýu‘b«Äèôø˜‹)Šã§Ò!Ëê gìÉ~ðƒ+ãÿùÍŸ~ôoýêwÿú9Ü~þù¿ßü•þÖüñ¯~HˆÆKx"±èáâŽñn%yžDÝn/>b'k~c°Gd‚WŠÂĮ́2/£ìå½:ÍYˆ ÊvhÏ<.OJ"èþÌÊn©Š®$«pjJC6¯ôНôdã6§ô.pâñ>‹ÎÔ*…>‚ü†÷TíD¯lª.@fVÂŒE:˜ŒXT‰‚%VVJû ¥£¶*Øà·ÐKšúŒùVìçÜEÌ ÁÀÜ%@Ìð ÓÐ m,*&dås[6î,mn ìo½”ç´”<Å4x0-±´ÉÊ.M%E‘ 9/Ñ%½‘'ºÑ'Fì¬,GðF"'MH/­ç4Ôf‚QÎ^‰&L‡"óà€ôpÀ“ ÕÌ:ä¦r5ò"òs%âþðJ;ó? ISÃI±#g6cÒN8 U£qU§ñI 7‰Ð7UU3þÁÐä”,º±9át D”/Oª 0XaÍSó­«ç‘2Æ æU·èÌ´ƒtT#¥ÃÂÐVÓ×¢k†¸’!äP"#\ý3@uÃ?é“1Ó!Ñ5"ÕPJA¢6-AýïB-ô@uBARBó•ß³_Ûç‹«îdB2Ñ'âô°X’ ânöÄ…î Ñ_ª3âF$!,–Ír±h¬åú톴$™Q=vÐ:ÑsPÿ T[b)r Ü\é³4ÿsE“f{ˆe}Q>mö?ÐOôÑþÚ EÇ4hÁ2צ5-=iÛ²Y;Ïh£å$K–m¶1/}uWsõ“¡NÛaD#U óól¯yŒc ÁO[j"‚8v}¾á\ìP{G:ÇÊZ¹U . ÿ’ب/JÞ°o#ò Gó3 "!—0ÞPJù“>áð"Ô°TãTYvÿ¸VÑ”r[õréh1÷¼J¸„“/ õÔ -&¤¿‘éât»‘,>T&u.ÏÔF Ƈ¬ê>ÚÑÿì+?æ v³¡õ¼>iÉñÕ<Ñé)ñCe{ë=‡ g4 ²°/ZÔæ#ÂÕIWj ±Ê”6ô`Å{!«ìÕAcÕÊÆ7b‹@gÊdþõ²Sa}&Êm.Ÿªp¸J'8…lý¦rBøÓ ¿—¸0J5YF#Ev¥âÖGw, EY«+Ù¨LÃþtÜ¥’˜I«Ž‘q…ÇáºÔ!!vÕôƒ£UxÇQÒÔÓsr Vi“²p Ç„ê0ƒî~¥‡æç°5+9àM‡£Ã,B‡k"ŸâVùPßj ϳäæ6‰‰7diˇ֊¯¦d#c˜î_Éî*úö[‡3x¦‘†-wVɘGC²7iGef8'·îK§K¬ª)…5òVí¡ð—KnGØÍT8ˆ¬Zj³/l9-ƒD¸G²ù2'¢ÏµµìaýéÃ0þ„³<ØÒäµbT{$Ⱥ—wÀ÷|Û†t&´Õ•”õ:î„B"‰6ùϳPï ‚)ó²ƒSŠOYô'FI_~oS†£,€†59ÀÌ ]è8û'))×­¨˜äøL!x<ó ÃÌ#ép*R]i€‘ [är§,æ…ü·ÑŠöÎÆ„Ái¶Røc# ’V‹Oï; m=;wEFOýd{47«ry z¡]ƒˆç•n«µµî6¢´®”m½Æ‹Ä+À‹\€5«³Ñ<ÍÕ|ÍÙ¼ÍÝüÍá<Îå|Îé¼ÎíüÎñ<Ïëüa\‰o²%À«¤¬Š†ã8¨â‘$ºÇö?Zhñ,‘þÙ¬šY­²Ù±À¹} 4þŒ•]kt¾÷=¾Õ¥Çìºn¹¾±¾Ã oþº8ý1’õ,õjéžé•¾é¡þ饾ê£þê©ë§~ë­>뽞ëAýfˆ=e´‡Ì^*ôý®O+Y醪âWÑšN™5½@ •yUQåÞ¯/Å{›ÏÒÇ燾™³wð˱MÉQRaênj0ä¿ñ¿+Ôµ)·äŸ¸¥*Ù¸p é2 ¸Â|#ßá»\”í[Z÷m,]èךõšªš$÷管+ÈŒ>œlÿSqÿöu?÷y÷}¿÷ÿ÷…?ø‰ø¿ø‘_׋–EYÔ\Ìi{XmšÝîN s„+ú¬¼“˜=V‹S:Äñ©ïþÊh[šþ©G™¸ÉßÃ(‡ô¾%,Ÿ?QÐãcñÿþñä•©HZlK3Bçš@|BKT Aƒ ",˜°`2h@›­-:„ØqĆ GB„¶ðáÇ“6T‰ò¤Â˜/!ºliÒ$É›söüi0"É™Bu 3hÆ"ör‰)Ô’@g6´z2©M–·fU:µ+K’a3nĘ2èôP×®d ÷­\±qéÎuk7/Þ½jû¶õ[—ïßÁß5ܵæÑ•*É:– 9Ó"½‚½ü¸èUÉ*b4‹@à‚Ï+)Vn,ÖgЧ%‰V…Ì5læËZÉ–MŠviþ —SGUý”d2{EŠLD«,LÛÌ“÷þ‰u³kÙPYƒe3·ÆÐ¼gcÖý=¹÷²ã˃'Þ¼øôì×»ï±öد–w‡-N™fýé¾}Û.[Qe’!°Hg%RHEˆÔE‰ä ƒ nÕoï%ÕB›Á‡“t‹aH•~!.O÷!‰ô-ÕK0™H]QÖ‡—\Ö͇ãs»©¨£k8•z‘è]x¤‘BÉd’M.é$z(Ê(b•®=„_Žeh¥W;UæYAÛ dÑ:Ø‘GŠtfE%…]j–ö¦s½}i½É‡¤w:÷§TTN„F0Ú¦'ŸÀ]·gþOqƉV‚*U'zcrUivñmš'§šv ê§¢fJªœ¦¢†ª§¥¦ꪪžú*«£Âj£+>yëd•ùGa{«ù”æ®Û%cæEaT&Ÿk²îÝØcN&¨gŒ3zzÛ­ý}9eˆ\~ íTÅ5Eu7’Hb¸ý1fᜎÚÉèkNôãDi%”úúŠkŸüæûï¾þLåC‘&—[}1IVÜ»¿ñ–ð­ ÈYF‹p7á„Æ’ ƒÌzÄæD›áû«xŽg­rTZxpˆ®eº¥Vв¼¨J„6<˜})#ê¢f>ƒóÃÐùµžívu)}+pÓ÷ËôÓK½ô9¾þdÖ$éJ²I-wIíIb4lƒÍ’ÙÑq¦… æzWj™³{¨]ËkŠ)OýZ·¢VÉ·Ñ?e©åt‰škç‚χ5Ö°»XmwkÓN5yM–Ó]9æ”o~ù‰šwÎeæž:矟Nºè¥Û -”XâŒáÜR«œæg—f›»*»1˜öž§”ã[Î$«¼Æëh« <ÏÚî<¡Äzw‰€^4òZH]×Ç/j1wÏCM>ÞåWm~úè¯ïôÞ¶ ½¼o“•›·¶*ò¬½ÃšF¦‚iâ ëLUrÏ@wž°ÉD0;œ‡\¶¹•…Mo‡;Úã`G#èIÐzûU¸þBÄEy ´Éþ¦C” Em…çk_ ©æBõÅP=„` ±Æ°üOfZ“k d»³˜!j«Ø®ÄRÄŽm‰yµŠ‘»,H§ºÑl†@ƒÛð¬è·LI2"«Þàš§0=,…󪟖Tä§ÇmS±Y¬ÞØ*ZÍJV®Š#åXÇ9ÂQvÜcƒ–<ª†8ùŒÞœ„¯¤ŒM°ˆG¶Â Ê@H‰:¢Á²ÅxÑ …"Ë¡î?8õje¥&ÿ†A32±oÐK\—b“Hç°pÚªß. Ã\²P»dŸ._È4V~ö»È¸¨‡Åbþ¬+µãÌ”ŒßUì3jK"Ün„µþj¡L›–áǪäÊZ9/ŒÔ“kn¦ÃaoŠûacgäÊ,V§žûZ’VF÷ù²—Tü%/ Ð~S7áìIé\Ʊ†KlHþ‰ÒX“~Ó×­ff=Ù‘ÎzŠù·üIA‘2eŠܯ6(•fÈK”ŠMCá%Å—&Ç–Aó(êJ:ÕéÔt©ã)NoºÓœú4¨@ê‰Ö@*2¬EuKžwf9ÀŠábF<¢DNRM—2´dUô‰7[‡°d*,~~³ÚófÖ­-vQ¬ÙcçIP¢Åírœ#m¾‚Ïzö“Ÿ Ýk@÷ù×öÕtœö %DY.Ãe‹žÐz˜6ò"þâ²NâIYÃõ¶`Ò3¥#ý¨ Æ:S²Ržº1©~„¹(ÏŠ1–˜—ºV)¹2F†`zÛÜú·»àb ú¶¥VEž”í_&f (4¤A™Lïj×§bk]FKª,¯éÂ@j÷Œ^»ª®Ö5ÐUšUS"lMÁ;·G©_Kœªø¨2›?âq¾w¬¯é{_ûöq¿|ì¯|‹wÅÝž¡ãƒe!² 1¦yÙ(¯TÞS|ßûdµ »^‘zË·ßgÉ8lÕx¬¬my-bøFKµÏÛ×óuÆ0¦±”:;Veò$‡§‘(Ç÷Ã01ÒLT‰e׃\ ƒþmvÜüÍW{öYVk]pZ—ÂÅI°m½ö‹½Xvø;c*.dD)ã«™·ifó.© NÙ’e"Χ“7E2+ûÓ˜ŽxôHh%ùB“­j¹©Z7¶»8Ö²RÆUÕoÖ¢Øt-YºR¡‘÷x QÒ÷¡Šº¨£îi©jjR«:Õ¬Fµ« M·‰7YZ+l4ê¤MÅrêU1r9EM»’UIŸI“‹J6aß#hÝVëö†·rUm‘Eä—=çCóâlçl&aºG/ ZQÈyú˜ŠŠøo€WVH€®¨ráÈX9!†0·FÂw¾!QYå|Köþf½÷5ì$‡€wVlem¡²E§ŒõÈCÈ^"µm;e\%0GU|“51èûȈý(“MÒßø»önxg %fiÈ,f$ÕM8QVUIEt”â5‡¨‡°vcuøKúÇhGR9ònÙㆷƒ'†kaÔwPõŵp-Vxs˜–¨–è–¸–(—‚g޳sAYfyF×n—8wK ‘ø¶k,A?•ƒÕ(i¤ƒ ¤L8hE#©d礎²–tuqõ‡<鎇TíµFC“5“4)šüè-ïS…{ÃŒ‘Ùñ&1¶øP|†øvD5˜±„shˆ“vŽI‡þxTtˆŽ{E)'€yŽ Å÷bŠ¥Y]Ê“ž»gšjvt²8™6“Ä1‹)ɇ3x€ãå.^ö§™/9ã¹BÇø‹Èˆ ª Å˜  º ‰9• £šbôŒ&öæ‡¥é’ØÑà( šzxƒåØh¥‡’•‡çxì–zÈx ¸Dù60ÓÈq×¹ˆ7š¤y%Êž5Ê)G\ yšt‰ËÕš%éMúiJî% ¶ž9˜‘§m9‘Y(&ºNï9~'v¤F¸"ýés.K¸¡Óeþ:Š£gšˆ7é}âØŒ:â›nd%”¢hŽE[‡¥š&]Ny•¸ZOH•Úgð¤Eøïh”¬>Ú~¬Šu¿a&å’þ¨LTм*¥ZšTºŠíDŸóówX«é –µ˜‹ªdœQö8-ɾè +KŒ-;Œ/k , ³=Ú«KR'oÊ“ä3ot 9 "sl"@fò³è×? ¢~"ñ•…é€Å†˜uxa‹Ù®ƒŠ¥úhìš®v±AÚB:> 㱋©¯Ëʯg«¦õm˜c‡èxÉFy®‚ªc"†Ž¤&x[´m’1¸Ã1³ù[N <٬㥨‰Ÿ!ÉNö‘Û ¡^„Ÿ•9…—yKÚ¦4»ø¤²þЬi‹¶Ü'u E8o7*i•ps¡Á?"ñ°œáH·G†t÷Ñ~ô×”ÄÄ8àþ€`¥—!µµWYZX±ƒÃòÈ|¶è“Ö-8DSše©Ï«©q)½œ:½—j½=ex¼+‚Ý OB|Ùg•„{hSwÊ¢~cÓ‚dI0ˆ|x&ar›I˜k}Š«¥Ñ6(ê(–“ u–WÍ'EZ²D¢¹¯Ê¹l¶ž+$êFxwF„¤‹¤R»«ôvá !fs¯[†dXDu‡‚`¤»Q9‘»9Š\r¸Ã{œT»†o›‡ œèE°ËÆ­p*ˆä(˜®óÛ¯ܹ;ÜWËrÜCAJ‰¤GOâ (˜&@{·æ›w R”g8l# tò;Å z“Ÿñ«®©~¸¨¨lE€¨±þ^j…þ«IÙ4}ë+1ë²l<³úÆ2ëÆÉxÅX,¡Y¹œkŒxb”ᦂÉÕ&Ò~ê÷?µ&¨è¡k{7á(¢R{Â{èˆÃiŸðÄ¢¿«.yé¨=$y0jµ› J‡ˆÀ<¬Ã܆¶š_†¼9IÆÖƒdZ$€DÊ9lÍŸëOlê¾(Bº/ÖR¡'E<»`YòJ I´\IV…Q‡F—ºŒh†¡ûgŽ)†Jÿ·Ÿ[™µ/¯SÊAóH¸šYÓ(ÊØ©Ð{ÐÑK½ }þ½ mP›Í«\z#Fl·WQOü—YËWåÌÞ(º‹<޽J«=¸‰ë®у¿6^)L±â7%1|x[¦˜½¦ªÕŒÍ¥¬Ó5¦ÀC*Gš‚³.)¿Öj‹~iÕ˜D~ÉI_Y¯æá†"œpæ:"œS­x‡ŠŸ'jÕ’æ•@ìÂS4à l†1Ún¦œÓ×<ÊùzÕ ÄÛ¨&˵̄° ™²iÂ|HëùÊ~ÍËíœ]›Å‰j|(®j¬¡;a+¶À<[Œ¶¹qÜÆ ZÙp<Ç–MÙý5ÌU“šxL¿O‹`©ûÀ¥Ñi¿¡P[X¶ ì´íka#íÓ>¼»ò<^þ–XuÙŽ¸Ý`­ ÖÌéRHh$»¨Œm½ÓkmÜP 4 •(÷ީܘbH(-)"²Ã^èÉŸƤD·@…›’‡Ë¤T†±H¸±ºªNÈÇeÑ7­<À͹²‡dljMÜlÓé½i´°YYÚ8ÉÉ|\o  Æßòͼܧ¸[œ!ÜÂë»õ‹¨$­$K¼ºM’:²2©Áw)Îj Ð!^½=âMâB•½ÄFQ*¼ŒœàÛ™ÖâsñÞà àáVh“Ýê—íê«îüÍýVÿOŸÍ®ÿÍ$,ΪË;ŽtD£ñ®Ï6Ãuõ›íí¯zÅžâ/•ÉÝ’¹û’yáÕ&ÓZnüЕùE·ðžÏùŸŸÜ<‰ áƒVP`A„‹,„–l`B‚¡|˜¢Á„/l€Ã†E é1™G“-€†òdÊ—Uvl˜¡Ä›nÌÈ1gFž-æôùshAœ}&%ôèS£Q1FMêpa‘šH¡j¥jóâT¥:%»ÓæÄ³9r¼Øvë׋"ä©­P¼þRÉîíÙ7/W½~ÿÕ ØpaÄ| +Üø0ãÃwó2M,” U†‚m.ÛY`ѯ2AÊuÈaéÓAf]PræA²‘!Ö´0hNµâ. ¹òߤasòì}{«Î…öfÖ& •·e‘…Ëž>VjÅâ]9sN&—kl¾>icŸÛ|yôµÓ“Wßžý{´ë㻟|}ü÷õŸ§¿_þþ¡ŠËÎ1ĺª&·°#0¶ÂrÈ$A +XÉ!‡¢ Ó\ µ¨6N3Æ‚3 2²¾*0EÛ¶ÂM³ÈTTqÀé0+¤àÀsn3 jFèz$Q2àÓL®Ø`ƒÑ7&—tÒH(þ|RÊ(›ÒÊ*›î:¸Z4kD{Ôñ-¼œz¦FÂp¦ÕÎÊjÍ3Û¤ºò¤|Køš 2Ïζcn·mnвƄ&¹³žëŠPüˆ\ ¯àd4LÉ?›«³¬.i‘ï¼2/Ë&A½RKX·lpÄãîÔ“@"Y½ÒÐë T¨‹’±g¡ õ4D!¹Ý6Ñ ³£ÑÄ'ó,¡^ûŠ3»ÚEöKx—W2yë¥÷^wµÊwÞ}ííßwý `}ß-‹:Q› :igK+#ÑB`‘at3«7k’óºfþ›¥±:G«dQ@Â2­ôX’µÕÖ%C4×=e4G†-½×MCnq\Q‘+Á„WEuÔT Úh¡‹ZT?UöÒ>7¤ÜM«¼31òÎ.›)Êy9¯ÞSÞ¥wüË.iïmdÝî8mݪ:Ûß.òim»Ì:?ïÎo .ª µ3¸l¤G|q¥'úñ£·VI^¸Ìo)kY§¬GéϯÁÒPçèVÔ À9]m;Rã"O¹Xš_—9¯— ^›ôFifîÅG¥“nó¼Ë]û Ÿ£ ¯?þ þ/ùü˜÷ù壇~zå©o^z¨-8é¨gÕYwÇ(åjW'îÌGþÀ 9»º†4Zñ6L“Õ»c ?íÚ;ž?øhAJ€{ãÊòBðµN*qùœ¶Ö9Šsœ-AcÈj+ØåNV²§õî0;”šºU"Åh€{Z]_üæ°Û±nmš«” µ·%ÖqIVÊYêŠä*ÿåŒebZaݦU© ^fSS3Ý¥(8AÆA±‚|âŸDšJVXa" ’r\=ÍA-IIM7¡í ŽcŸò£fG¶É…l¾‰cf¼û½ssãâ¢Ìæ6Cé©oß‚×qnÆ–»¥¯Oèj Pø/H,’i%9XI~IR“–œd&9¹É6ìYþñ ïÊ&ȼtNbs9áÍîòÀ!™–VŠ¡ÈlSœ¶mp–¹3‡@…dÆ•8ÜqJÇ zÑfãˆ7±©ÉRŠÓ´b«9E;f³2슙.?e©‰Rœ¡ŸûÈ·Ê©|,!k›¹ZwÊñÊ"ÛàIÈ;ÖZ©)µ†™¿rÉÏ€è‹%¸Z)D¨x³|ht7¯IM*Z3¢Ø”¨6“$¤z ÏŒÂìáûf†)ˆ¡Égæ#èÁ~ Ì©œtZNä%òƒEˆ—1K @DÈ®”¦E|TïÂ;ûñ‡„jJñ©Nç%{׳Þóª÷T¦BÕ©Q¥êT­šÔ&Si[þ¬I­X*¢%N í¢GG).|"µXõ# õ¦PoáQ ­$Ôå’9»yQ~úC«þÜ—¸3êð¡ƒhL+zXЦŠ\-çÅÊGjo3Š*KÈÐù³¤¨û`EЦO#éñlçrÚ ©-_ö²›r…¬œ`ê×Fs\{N·¸rN…4˜ƒÕ.kØÄW¸„½bVO«`ö™ª¥\ÍÆ'´¡öªíô¦¬f”ƒ±ÒnEÓöÝnµo&ýÄŠgïW”ÖM}‹¤¡ÃÚL{.4”ì$&í{IüÖ7¿ ¼¯~ýËßýR׊)¥y'¸Ü„pSnnye€¾ã½a«ÇDcY€>ßOƒz> çšês’vŒžp»çÝNCÆkvíŒ.ï=„fÓ„þЙH+’ÈëD²“Kµäó¦âí”Êm[×Cù3šv4þ ùæp1Ø7éÓÂ\ä;ë½áx¿öÝ »æãj´”þ~JF§‹ˆ”•ﳯKo•³Çë}6CÌw±ºéWm©yÖÞa*û¼ùÆùD*MLŠZûŸæ¾¦»Ïiï‡ü|v¾š%®^GÇ/Þ?>Táb×סo{Öö¬ŸüV°Ã<¯žÿkšÞö”+¶Î‹´A$}¶¶"•‹6×S½…{@Ö[½Ñc¬àK£n[¾’ú:v«,©óœÝC¼-97ÿ9>S#>; Ô7Éë-y3.zc­{ +•zÁ€*¸»Ÿ$þ=q·:s·¬kÀÖsÀ„ÀÇy¸æ*Öú™ÝÁ‹—¯ÛAÎ4™ ŸÃÑ®‘Óµ’;°<êB {—…É ì»yBÀ,«B4lÊ` †z:¢;:¡“à«Ã¢›Ã8ÌC£s«˜"0 t›UA@ÜC“W+«øK?º¢5Dl²=Û5*Ì¿Ô+¿Ò"»ÿ!¯@±:tÛ:éë7µ[#I“£B BR$BóÁ $5ÀS.UÓÀÎr ö»¾F”§dóc‹œ¬½ýƒ³E±sJ°¨G/£¾Ô‚´ž:޶ûJG²3ʸ„ʺËITDËk4E#dÂ5 'Á£0²ÇÇ‚.«ˆÂ±ìÈ­ÛHn9¾ÓF†;9–Üb䣖CFK¯fü°þ8´d2FzC½¤Ã;´CʼL=ÄC¤ÛLÍÜ ø;« t®£ÃÔ7Q|¾¿ô½–BÊØkÄ‘‰IGü²¶ Á%ì<{ë'ŒÑ([Ÿ¡š-OlFÆ¢¾Á›;sËFµ4μFFì»ë¬$ä·¡D7rÂÈ(<Ç,ü, 42-B2È{¹_\ι²¼+æ«B`L`üFe2ÀLä=¿ƒŠiĨHLNäLKút@Ø»6óÆ*”'L$ŒÜ3ª„ê:fN+d)•jÇD³xt¬äãCo4Ý"v<¢Šl(ƒ:1ÄûEÝsÇmRȆ ÑíÑeÈuÈ«rAóK Ъ/Ä82â÷ó£žLþ¾-lŒú‹Ÿ)ŒÍUÔ¿’ä¼`˼)S©^Lº +EzÆ4d5<š´IûŒÒµíùΩ¤»G´JäਬÜÐÚ\ÌwäJ K̼Ôª±¬R* Ôû,¬¶œK#‚Ëš‘CÍ›'Ô8ÜS[ò)+´@¿LA-œÌÄ1Ò|*RÉX9Wl™ õB³`Of¬-/éÛFÒ:¼Ï¬LWÅLδÌÌ”ÕX}Õ8„Pxdº-ý8¥²#DªCÍ|L/ëXµELMûSQXôɧ„J*+7ÀØÒGlÓa…IN„>f¢S# Å6)GAþ•ÒúœR ¬%Óž¯ 'ŠLÒå–Y¬Î,Ù.í¤/]äÎ ÌœêO¯UEó¿› ›:Õ˨—¼8Øô²uœÏÑ68WpÔAÝÉüt£nÜÕ;ʨ%­‰ oõ»s´Á 3S}Êz­\­JƒKÌhå¨asJ ½´b; }» ;Ä:¡Åc5Q„Ñœ=Q%Ñý4ˆ\QDõ”ZlLŽÀÈe«%´D!øI¥ËµƒÝÑ1ÄÕ %/çz#6|ª.£™Ç\Ö'UʆýV†=[3ëÉ÷üÉö™½ âµÅ4J1]P(-Nus«|7 ½W‚¤Û [-”ŠÁé˜Û{t/öоþÏ›¾Z‚k<ˇ-ÛÈEÛT”D·ô¡õÐ_\¦º,£»|Ô/³¿pÄÔ¾ÄBdu<Õ×MEÓNR@CŸzZT¤~¤5œÎdU8¬UXíLZõ][åÝYí9\5>]•ÓgÌÔ µ¬`²xM޼YŽÔQÊ%HœM\ÍJä(>ج©˜½ÁšCBÜ©ÅgE7uXÉ]_Ê%T5]WœÈµÛ¶£(¼/ÌN Ì@[œ×*éÎÄcSK OaŒ²0YØA›4CùTÒàA ¼‚Ô²ˆOyUßöÜp…¢ˆ]«‰E^ЃL<ýUPƒ-¾Œ^Õ Y})J\:±K;Ž´þ)ÜÌMÕM\NlàùDÞ ›Õ:œõY!b"FQž=bV¡É1tŒ>‰”ÅdÃV½G Íßzå:ª…Ä]ŠÚ®=OÌ» •ÌáD=‹ƒÝF³WfMi4´à †c9îÕõÉ, Mò•ZÿT æÕX.Ü’-¦t¸ ÔÛæ[œDzÁÀa ÓÊQÔGÛ”¼¥ËÀQ¨²|Ü86ÛMÆàÐRÖË=TïIWæYÔÖiÔÏí±)¼á+)]®U¼K6MÝ?´K”ìEãc (…-‚=œ 3-7ô5 ÞÞý]d^à=fe6É@» þÜT-J`]1aEa®½PÖþÄ×d]äè\ÛfÇ ƒV—qä#õ^?]”—ÍדٰµndNžcOžgVEfmž³ÈܶĨûeÕ¸³×[DÒU•z]+Ç`X&`ßF~¢¯’É/NÜ+~•¯=hg0KX3îdöé 2ÒÏ./ÎýÉÛ!Í™ÈØ£ÔAíÝ¿˜NaJTPEÌ7=YôJY².+çª;\cµh+ƒäDþáO.âžUj$b#þY ÚˆbbU^\AÚ)¶R®ÝùóHÙM@/¦_”íÅ®½æ†àŸ‰[IßÛ^å›”N4ÜIš ¹ù iz¶k{¦]%»;ö¶âõç -¹ýcþÚÄ1Ò|3ÍÛ5Ý[©Ld@öf§y¹züg£.Î&¼ìJþe -aŽV¢>ÅgÈÅëzí.TñUt_¹¼A°Ì¸T^Ü]¶QÒ½ÂW~Þ²îCÕ¥eÂŒè>ÊÓPÏG nU]c§€`ÜÍ(›Lc^námîefîçÞÃta>MçÝE÷QD ž^¨U—oN"P.lJì0aZ5ð}_é@¨ÎèÀ†V¹[±ôÍkѾï‘6A¥_;?’IÇueTû,Ôß[üà†>²ÿÍb^lìäÜF1ŠðÔº¹ªM2Ru SuFó„mf¥`wi¿ë‘Þ`c9éÙEäQÝ —ÞþØæ,ÐW|¼¿KP;3Á™æÂÖiå*ÛbY%¶V<ÂV€£SaFê{~j§^j$gj¨frM+oŠbbRþX‰„ÑÏH­âèµ%­èeÝÔ‘LàXÒ=±«IÞט˛ó4±"ai/б­5qûžRµ…«¾Žæ¼lÒéc¸ @tAtB/tC?tDOtE_tFotGôD×¼G&ry>gÚÜ™úµŸxãì÷Ìä íü¦sÒN8Ó¦òîqE¢]왽H»,!HuXuYŸuZ¯uD矙K<’|eCÒMøÎ nÃÈ$ædffc‡îbGöf~Õâ¥n·]Ú±ntþ¹kþï§kçòÚök'/{èvpOo÷jçöqÿömwuÏvq7wmïvr¿ xŸ÷twmW÷x—÷tÇ÷uwwv¿öøFg|nbeêXTÜw®Œx®ïQuüÆFråoçäçygÚ£+—÷?÷sßxçxkÿx‘ù‘/yoÿwtùŽ?ù•÷x”oy–Ïö”ywç÷B·ðŠÖlù¬]ÖýgNß%WUPwøPŸs5(n„¿F‹]^0%¸‘ˆz©Ÿzª¯z«¿z¬Ïz­ßz®ïz¯ÿz°{±z¬ØXìÍtÌöD6_¯Tíá€Ô\wTr¹oj'¯û%¿ûs¢3EÂÔÞ±Ñdõþ€¾¬‘‰|Ã/|Ä'|Å?üÅO|Æ|ÇüÆŸ|ȧ|ɯü·|ÍÇüËïüÍÏ|Îÿ|ÈG^8•ÝÆLÒ%-îe”oÓsc(-ú:'z ¼s¾J7»=VB©ˆ‚;`ù} ~à~á¬l!~ä/þä_~å/þ1þço~æŸ~é¯~ Á ¹©¹¤A¢naKßa÷$ïÆÕñ¡7úØ7ÿâ‚ìPFíÀKÔÕÎl(¾òZ‘¬ÿ‹qDãbýïõû·î|¶€€&p`²„VÐà„‹@DhP¢@|ZL˜šE„-‚tH‘#´‘M˜1ãÈ$UÂüøR`þ`jÌY±$LŠ{Ý铧Р$‡"5ú³(Ó£J‰:mº4*Õ©V¡^M*+Ô”: ºœ¹,Y‹!Áè'Û±N]n,€B…5Õmȳ!B¾uSú |r¯Âd.¬·ï`Á€C~œ!ež•ÿ½\ø¢cÂ’=[λ2â…‰KD;¸mË®!ÛÂÞ Wík’µÃ¾œÝ6lØÔ-k’÷W·ÆÅ"'Nv9låÍ‹'‡îüøôèÌ©KÏ.³µK“Þg¢¤ ±îH‰+aW‹3Ù܆5o6L,P¾èùëã§oŸ ÿ„ôÿß`|¨×Zö8 ‚ü-ˆ ƒîW`„ 8Pþö¤¥›q¸¡Ôšk^]WÛu»uµˆ%¦G“M¶©Gv#Vcv0Îø7Ú˜ã‹:ZÇcu%Ît[,ž5žN¸É”ärå%4W^ï™¶_‚þQI¡•öa”Myå„÷}©×i¢M)f•[ff•Yf} UöZ2ªçaJ³i˜Ûr"vX§Ÿ9yDbLƒ õ^Ny²xç`ª¨£<1 ž¤‘Rº¨¥6 饚b:香‚êi§•ŽúiB™&º£ªWnœ®ª[wuµgáŠpV)Ñ–»J ¢~]QdÞ‰\öJ¬±¼BõëZʦg²ÏK‘_]¹ŠÓ«]˜–^³Æ†äE"Uˆþç†ãZ¢ÓÝåâ°2âkî¶;¤¼ìúøî¼ö:'âq(žj”SE¦Urü~;¬[rÑuØ]6*“žŸW°‹v‚1ÄcEœq¿@ÄXk¡røðÅ#÷¶/(Y<’8+·²ÉâP†G±W/»ñjP \îpø/½ðÖ+tÐE#M4Ì›¦*䈶:pªMÇ<¨ÃìàÞŠS?]aÅc¾&z]6Óá­ž·×¢m6¬V“õ±Z©a˜3k- s! ÉgÏyj(äH†î›/WZUuøSˆgµ¸ã[1®8ä'¹å”Oe°·F °z(¿ûjXN*l“|_R ?þ-Vë.Ù¯ê2ÓÞºn«SíúºÃâÞ;×Kã½/ª*©;Ù""ÿ-·_+5¢žÝœ¿‡ó½œ'}}öCk¯t÷ßsßwϼËN6«Ú²ì7ØL GkÖ.rK6_¶D6£²È¯»½±‡õ‡èEJêŸÿöt"§ÝÎB:]uvó¹ÄPcÛÎѼ¾‚„ÄžA¤rM\žsàWÄg-æ ìI¦ÓI¦æ÷aÁ*emKÛ”ƒÃò°j¢»!ð€ô;‘ˆXÊ CˆØ£.8sÙø¤V3ãð…±É›îPè››T‘8¤‚ÈL5Æ2–*dÕþÏÈF4¶ÑŒrTc¨R7J ª©ÜfÆ£ΧV*ãk®5‡%ËœÈJx(çµhv±Ë"Òf£¶QP  ØulÆD (IMˆ"F±s90]Œ,Ñ!¹=­ !ö6®õùë'+ìÚqR„:ó‘Î.¿ ×£>XC½±\¯¬â·ØçÇÙ²–s“çµSVU—¤ÍÓ~É¢%jñDÜÝô°­.b0–Ë\§+ÛIKv¾³ˆ¨r!5Ń>öYì˜à¼´fN¢’˜—»eËNø¢Vn’)‹ @ý5É„nE™æj_BVö@ó}'Ä›íÖbI6jÜZFÙþҸɡ¢*=éJ%×R„²4¦.•)L Ö͆d—áLš `–³kÞ䜸LÖÈÝ”„† #/ªÎ>MŒ ‰Ê–;yGeÊÊ€Ökèj¶Ê:.VÇ7À±c:e©NwÎ2­gg9¨Ìuj-{´"É·ÓŒ`ÍŸŒ\åÍf„J¦,”+nm%w( ½ Do–}-éÔ\¢Sr OªW¤ßß(‰NÉâRb,é^תV³‚žŸ­½ <}©PŃ™(éiD“•pÉœŸÃàH¶Ÿt7‚cZX.Vído”nWóLȪöž‡eZòàÆZ®Ð,mOÃ!réÙÙQŒsŒ#‡ëþÆïn—·Þ ïx» Þî’5»&´gU¹ÉÓT1Fz´ÉðÂÖÔ#í•_¡.Rƒ7ÁÞ´¬ÁM!Ð~ôQ²=Ö°ŒEîÝ’?ç2°ÀE×0WY\´z6áÅð†ÙŠÂØÀÕ¥ÿJîç‚×!Ú'¶6A ‹[ìâÃ8Æ2ž1klãã8Ç:Þ1Y\7>V·}üóˆÉÑ sœãV%ÕáÑr˜´OÖ0i©X.§5x®ÿò••·œ¼ÚªÇb3™Ëlæ3£ùÆ›”ªWl¼šò¡žj.d÷’24f5Ý3æfêg>§”¦}ôK)§9ÿ†Ž$ îa¢ëúÓ„Ù-Ú$³eþI[:[•Æ4§3ÍéNgzÓu¨KÝéS{ÚÓ¨Ö4¥7IêO§zÒ¨žu¬5jZ_šÕ¢^sǬÚäç½ÖÑ”pRƒL£éõlTŽ2³=¼lg›õÃê3_o+5q]%³Œïûèíoƒ;Üâ7¹Ëmnr¨®¢4‘7‡ ÈÉê,ηնq6 gýN9ßRÞw³¡ü=ÓŠt¢f!123j(†½NsŽKÂpGúáeޏÄilÏŠËX¨Ânwî,›XŸ ò‘Ï9/wK.^’Ÿœ¼(/¯ÉYžrô2—eÙƒšr»jðx‘ Ì4Wu­qÝóLƒñç¹ö9®Qt¢ çH_5—.t§þo2èµÆxM ðßAÒ¡ÆFÏñbágû;ì`»¾ žg›–“u±¨}sëÀž–(˜v‰â¹½=à ÕÝî@Èjó^núªÖï<Þo¶BPÁ‹]¼Ak“dš…ÉêTÙ¡ÍoË÷›ì#OoÀWEóö–oSXn$·÷S¼ûyõ‰$ëÇ”Œøi²ºJ=íWo{Õ3¦ °‡FÝp_{ßßþ÷´Óîì ××Ç÷È'¾Ôå3ûå·>ú§IÆÖ¶ZÐ7Åu>øÁ¸`·:Ð4ùÅOhA›¿üáÇhž‡–S‚C8iÛtß2gõYÇ*Ö@†™ˆÂÈþy‰›´É0^±þ蟚àš áŒ|@ H þÝA ›` –¤‰@PÏIRˆm¼ˆUõ€ØU ^ž føMMˆUÛù€SÑÇ)D­,Dñ`†FIšFÇlña ´‚ü ë•ÄÝ= öJæ¯8aN_¯ì^Ô0à^àËëI˜ I›H`¢Fõñ÷‰Ï‘žÄÀ`÷‘C± æÁáÊ᳜k¡S‚Á]ÚI[± „ÜÍI¥[—¤‰ Nˆ‰ â. þ“n š(`"ž‰BÜâGˆ  "R_#.!ØÔ'Þ\Bt ‘…bð0Ør ]I©×ø¼\Ë­\þ,ªÜ,š-¢-ŠçÑ™÷|^¯½Ð_ÝMûô«lÉ"˜a!'#µ]a›\`r’]9„$ª ®øÇÖ@Dº_¦ÇB`c˜ tAE°˜“tîÔÍÁÝ:ZÊ.c½U˜p¥ æeÞ<Úã:E½‰˜.ÁFqÝr%Ü£‰Æ!Bƒ!‚"BA¦—9ª¡ATâ£Í]ÜG¨‹½Ê& y´ÃA&dBdBöÚüTdT|•[dŠ~¤A¤"´CRd~ÁÎ|(aJ"äJ"R(Rž(â…?ΓzdUƒ)˜’¥‡ä5–“­ =Æ!RΡÑXÙi XͶ±Ñè]”ΉGA ¤A þ$ây„ŠÇ@ÐÅ4ÄéÌPèÒLBCVÄV „G™)>ev¡@($$)ä8vË^¨åZ&D^îå&¡$ ¡åÀÈT±[mÙŠ÷µŸú¡ßúUæeŽ_úi¦efæúÚY½Û ½”ä°ÕÂåBÀåðÏRÌ$BHdÚù(þ”Cva2xdbÜ¥BÜemLÉ`Qmt`ñäæ[¬¦LxäØ@ã|(‚^¼ä^Çj–"I°â=ÇQå°…v › X=å=ŠgyÞËZÏw䤵ÕÜbí& ã£éÅx¼d”ì&âè×Ê$'Š%}¸ *Ätþf¤"ç@‚jÓÚü‰b~c]Ü%tREA,çZP'L`¤j)è~PçHPèdü#4^ ’¼ÙMxÚ[$áÛxº¨y.å‹R“nu^Aá¡9%‰úÔiŽG„®ÉJz¤A$[Ú¤q¦dÿÝfm"ÌÂ\Ô_F$”:‰@F¤€V©ˆò'HË[)QpäAl䮦Jé[’)#f¤B¤&o§r)…ž)G‚¤JÂå­àVÈ]ºiJv$B꩞¾$>¨ä]ZÄî%ÞVñW¢N8|… ‚œ,Öâ¤Þ"¥¾â¥º\¦J*¿˜;õ"]½#ö­‡|^‚Et²eªº)[®¥þGf%jhDýM©“¨XZ)”ÒªDò*4Ôß&†%u:–Ú%\ºjnk«©²–©²‚eàá©„¢*Hîæ´âé²fåaî$qö‡©>§tîæéZ†+Hn’e_â]ßDñÈàÄ#TÉhŒÂ¨RÒk2)& á'?²»¡]Š‚ ¦Å}öKqV«}ìæ‡~(‚¢é²GŠåEÂÈW·)éû$¤‰èXõ¨/‚ˆ–J§}ë_Pë_|kjîæ_'žhÚ¥V¾)`¶åÂF Çré^èip,uŽ)&:e›t±Ù- 3’E9S£^XR’'ÒÆk½¾ÕeuœQE%H5êèy·ÍþgÀÂeF¸jCx+ׂìËÖ…¹&)ÅÖæ“€Ù’NDFim „ÙÂɃ²ªD «iøh2øéÇ:g±ê-¹Þ­B@ãa|«A$hMúé›Þí«ìášjsÎìÀ}«~éÊB¨}æE„¢£Q™aæzàèHI&¢m&fž_gŠ.e’îéŽ.B}憅fßN›Â­]ÀthÁBèÌbeC|+n²,4ÄOš²í ÖÅ­V,]mÇÐ…®4,’¦é¶lÎ6ëZî×Rhá"¬(òçÌÊí]èôvlØ‚¯CÌdî n„§³Bï†Î¬ŠSÛ5ö 6µ«ŠììÛ­¼*í¼&íþ§â©§?þ’˜ÆêIzn[Αª‘d+îª*›nhÂ:ë«>¨\TlÅöa aXVð~d€>k« äO¤ï^"+Þ’ïšò&äúm’.¿ªŸ0O¸ª]+ÂþíÌòDà,ùš¯ôj%µæ%bZ–:Z]& ÕãÑÛŠ"Òý2­þ.íþ®Ur_º.Z\º±Aé@¦ÅöF'‚®˜gµ¾jBZïÅf¤Úo­¶‡ÚRD"ŒÅÆ–¦)VFnõŽlÍzqVFnäú)[â¦Öi–ÞmäžptdϰšÖq}Âq©úñA†i›’ë÷±÷GçuJWvª+æFO—mv¥+j*.޲¥–r¥¢2þ¦nj öd¨þ{q%ê×+3É0B׈•üJàšÆƒ&Ä“Ö߯ß¾É@üê7jc8~‰›Lˆ"³*ƒ0î|á•Hášôrö‚a*‹6RHüèÓ½j]JPw*Éc£3«³Òæ£Ð6¦ÜÜ(eiÛPÅ…@&FÔŒI=+³™¨¯mfd2ÔŸê5Ä“>¢.cÉpv¢ñ3ƒˆ2°› $ò5a1— 1"')3~äYé&»—a_¥>~QÑŠ²£t:çïJûÍÔ>åµh™—Må\UBë2Ã+9B§[îãBáf`Æu/E0f½îžˆÝöí”fÓct1³¢þÍ5ÿ3–(…ð9âAØDæä¡Ój\8w2Õ¸ëçÖHé†.êšnê®u[§µê^];µn4¶Ý{ù«=Ïnhˆ<ÓÀUJò_&*"¸xcö¾ ŠÕÑ81I ´ƒè‰YÊ9Ù)]#Õæ&NxtØ *)²_ugt|'ç)qJ¯3þšvýI%{Î`ÌÕ ŸØrX.ÄÙ1*V+J£•ärŽR ‡%ê')‰EƒÄMQËå(—‰4gµ$¦îwÁPßNZ_*n2XÏ›;ãüpV‹–ö³´w+ÖsØöã7”kÍŸìojÓ¦a/ðªžpS^eˆÜ_î"¡„’D=óþ ¦T vr“ü%/éÖ5ÌÂFXâ@õÛ-9G1Q€ò};Þ)«2)¯2…cø…k83v*[}*€¿—ÓØ´‘|ÝMŽ }›ÅrŸø $·D5u‘hã–™(vðU]ünàÍŸy ÚPãR—WVÖqkë)~¢v*˜S r¸«×sw“öw?ùhµ³4¦<—÷Q‡¨ÕAÀÚD—ÿÆ—wyüÄO˜“y™{¹MŒy—É™ƒ¹—§¹›“¹˜·9šŸù¶¾‡œ§ù›ùž×9›9›óù›K]œ÷ùœÃ¹¡º™¯9 ³¹Ÿ7ºœÃ9¤«y0™<³«Ï¶/v+Q&ÏzB¹JŸv”ÃRSÖèþ+púp™SÚd°Ÿ º¡·¹žG:¢¡Ûú­¿z¡ù˜ŸE£;:­Ó9Ÿÿy¢Óú¿£ º° {™'û™÷ú­»:¡Kz°ûú—W·³ ‡òö}˜lMæ[»5g²5¸“»¸‡;#Ñ(;Í5c*dÉîó‰}÷Zî‘G¼k ½I½G }GŸÇ…DÛ{5÷jqçº N„;Ú„o¸)?~*g¸…S¾)ëbã—,ÛM¥ÿQ|ʼ¥—aÙÔÛ„þÏ'}ÿŒ¾è&û¼‚~hôüÚüž(ºrש wº“O}ïïÈ”÷k¾†h6‘’3¸Ì½{¢,’Èi jÕµÙSîp'’Û—ÆX‡„é¥õsþþT¿}) á·°™7ÉQØk))ªâ¿¿#§;-Ôó~üïþükWÌ(/þEí׈ހI˜MƒÔÏD"h¡á#8ÐàA„ÐL¸àÇ!*¬ÈТCŠ9jl‘ãÄ…/n´˜P¤É’"SlÙ$Á†)cÖ¼H“¤Â‰.oöIsgGž#A€ÀæJ 2ÅH*E§S—VÚÔªÔ¬X¯>ÕÚ•*Ø­^¹~5[-Y¯sªT S%ÏdЊÔÕIñ%܉m×BÚÜ„fÜ«pæIÄ0%ÞH2Q¡¿“ÿ.èÛ7'ვMò 73Fœ*C R³Í†I¢dKz1ã×?Ïfœ»äÓ 6YÞMftÑ\™°õÞ-~õ¾WN¹Íåc’P­“F 8}ÝÝ9çªÉ÷Ùó¡Í_¿üÖQ/RPÃ[+1×™¯{#´‘Ìk·÷¦~ÐYȰt—³Am2dûÈ~è&6/uÌmÂÀ¶ VÐJcC[íê²»]èz%óÖàõ2Û°„ \³¸–ÃM-+ê+ß Ñw>þÖ}8¤WŽà”)…Ê8í Yõú1$ÍI±"¡²|XíÁÊ"T­f÷[©wX[òÌ–ž_O‹ôÒeWÅ-1«FèÙˆ—ؽ¦hGRq&+‘Œ_‡ûSq.¥©LUjS}äYHK2ˆ$¤"ý8(ñ¡Î†E™ßhÜè¦ÃDmœR ÑvؤJâf(AÑb`Âv¶õˆMm´éÐæ%ÝQ •¦ì¢;†Ÿ½¦…Ô[UéÃ’4'J ؽž;î ­[w3QoØÌô=3’Ñd&4Q—›\Æ0^à öVǺ±ivjbñÔM@Ù„2‹ÚÆRE»Ú%þP‚Vd§ÛR•*)l„g)Ó;5áe';æ1÷¨¨›á¯~OtׇF0˜u“f%¡.¥ICgVT‡½¨ö%Q§ÙI›é)Ì8¶Gjµ²„ÄÌšÀ·²P–HŽø©4Ê”ÅôÈt`§óÕìxú›zÍ‹9jïNGÔ™>F+ Ø.…¦R!jÇA{é1ô*nhB‰»œå4—9Ì9î«[õ*WÃÚU°’­®ê¸äRã ‘:Tsåé²z§:íLáfMpESŒì¨a•R&ɼ ›¹¾uŽßëÞgoÕíœ'<'W.Bù7å]°>q­Â\Ù-˜ hǹ×·õ‡JjâUíä?ÿÐļ‚i6°ÿа=ú¯ÿJÎÃ2íÆ"í³L»ð„DMÔ”%¢LÌõ¾½/üº¯}n¬¤žèBfkT`£ó6/¬HÇZ®W"fÑNh"®„÷Àe¯˜ÏLj/ÑEùØ FÚ¾ÅìÌ ©OÄèêÔËO|‹ íÜÎíÛÆÍܪp ±ð ¥psÒ­™Ö ý\…ÃJ¦¬®c†X2 >aLÆÄXFÿ¬ep:„EnAêêXE²ÈoÔ ‰þ«än/áÎ¥îcøçuêd eD´Â'ÑDÐãHü"q[„¿„ëÆ¾/ìyFMá è”Dˆ‡®¤g;²¤K„£õlPœxfáš*õbQÅ”‰:æÂÂÐÝàˆé¼Åéí@) 5J&â… 0ë$q+}¶Œ„zhÈNϪuÈÿ" 0M)ìC¦nI}n¯šZˆFú¬ò”ñ8Jë‘T0ê(äòêöâñÃ@+død÷@oÓV‘õdñôô±ùÑôrõþȃlšdïín Eg7ôG÷F±Ÿh*$bব©db&YD:O•®@öPí°›Ú-qþR‚ÝòæY¶e©ª*Ý„,3 \R÷ÔL™¸Ïw2{’ÍeüJ²ÌÌ/=„ðÑê¥U-'Ê0°Ñm\É–Ò&m,£”èfnðÃÖQ×ø¨šÚãÝÄ.+;O,å-òë⤪ö e*ÐÄ Î=m-óp™JíÔHJ'}’ñr÷RÓžÑ~@jM0×|â’rÏꮈ*ç¦Kl©w^I‚Ü©mRèD^+$ÍÄÝÊQ/­…\¢nq‰°Ïö¦ÍúSO† g÷¶- ¹ YS [Ó as5cÓU3®H­ù$­\® çí(ӌʃˆŒ,È‚òÂèýfÃähÚ8)¶H²þ#O2Õ SeŒö.ú8³2pêMúêeíÒ<óò<µÎ}bÍ]!iÏMR7Ÿ,bVî7»FÞ.ˆŠ€G?ñSŒ6èÁN›,„g@®µ%,©QAýò;Tä#nqöœO€vq$ÈPª/)2I²Ÿê.Ó³<ÑSD!Ñ´4¥1ýø¬-]¤ EDÍøó•öƒƒRñ*e‡?Ç(!r4DsÙ43³Izqf:³Ýjc¤Ž`!CL‰H*î1Co Ò© §K«4Kã§;1Soz-BW°éh× S&8[i2ÖiО*±°»"++ÓÐxQ>…’íþtC Äí¢AÙú†A·%=%V‘ |Öl/CôQyDçì2§³„Îo›øÆ&3teÀ©)â#jJ¨FU¹˯ÄL,Mì¼PFZðGÔ/Ç2VÃÓ&ò¬ÿ|ÔdV•ÓV%µòmO3>?0RÔX'U/ûÒD¿4¤àóV'K¡~,#Ït§úê)†ªºëT HbŽ*¯J3ES-N–cD—£h~”ÖŠP\‘ŒÌ<¤Cš´pbHÛ.s=es iÓ5÷U_ûu6+GÌÚ 3¤<+ê¨E#й²uÂJµ¨hÐ+ïpN9µó´/7P:3ÖbMP’ìA!UcNĤ.þ£Š»Œ´Eñ,yY[¶\%5/‘: ’äl-➨…LÈtŠR«¸Š+@©¬W‚ö[Sj¡˜cˆÚQV—V—µò0õtòFJÔàhò¶²B€UO/¢C‘åa¶X]6lѳD韛PT+±«-cåïó¹–Ï*¦I,“öìCQXÍ•\ÇVh„47#‹+ÇÐÏ©~LEâ,Ž6íLãS¢¬t÷!×q#—r'·Å Ró LEÊäBóNÒê`’sqÕC6ê¾¶„z‹$U.5vfWw(! ˆÂ‹u½zü'H Ä ñ%Ó%ÍRƒl…7ƒÒR jË.Oå’U˜rþ<±²ð´a”@VN{Ô/Á Õ˜,»×UÙ1i<3-)®/)0s•ôh÷ªp7”PérX'Vl‰7~‡×Õ”5+Ã)0= ¸‰k¦UVðyŠÖ~¸ÁuQ7Füöe«Ão77ÿvUé¾~•Ðd3ôú\Jì E÷_óµƒñ„_S„ùµƒ­WÝp;MIÙ/aÝV=â´¼XF{ &FΚ$3.ëìb_wy]—S7¥(q1;Cv;G¶KÕ´ð&‰÷ìy¡‡oåwçw£Ö3WaKS›•¶0.€Ö—>C±dÅH3dwÛmXòƒ€‘à E'“vog޹wi ¬":3tÆþoj‚ÁîP53†ÁQ©³kµê‰é÷X£˜µÊ6ƒñëo3Om1 PF©†ËhG‹Ï/XoF ~OD ™åp8Œ±÷g’”Àœj¥$?/JóñJµT–c™–%wKmÙõdmL‹ ‹yL¼, frË>ýlˆjJvj>ýo”.u òEÐM‰áµu{˜š©sVNÈŽýÉÝZò—z—Š­mê¤y¼–8D´/w¡”¥X1Êx÷yƒ˜`¡W>Á1Þ Öâf-~¡s’:W-µ'åü÷ív-¿ãm3q;]ßá\è³Y|ÄÁƼcÞÃIs¶i5Ûëµ@šÐòÝò ½ªKô„Ñ•`‡;}¸ýÝAÕáþryÂKðK!Ÿ\ì_Þ„¢Óå!ÂçcPþÝ+J¯yÔ.éX Õ÷Õƒ¦éÉóçß¾ð±|þÊCÝ=7>y•®Š×ú½ó{ãÅÇQ¼ðÖíjòù뺧û›û‹\ˆ[[E›N¨Åàcû¯Ó¾VoÛCÝÞýùýX¸Õ=…}Þ‘…éßïÎÌ2/~IY ðA8P ÁD¡$¸PaB‡ BdøP¢ÅŠ>,èpa‘Ð’M„†¢IŠ /F\©qeÊ'Yr„IRæH q¶,‚Æ—.5.D8t"Q¡HUj´iѧIkBe:UjÔ¥V©^uºµ*Ö¯\™&Äê°ä̘#ÓüX$dM“:Ѫ 4"òôY–¢Ù·ÿvÛ¦Y‚_Ì1'`Â.þ+þ¸òCËc/kÎÌùìQÁ“Ù™òäÛt z1Ä¿a#{öfiÈ<õÝ,÷vÚ¹µû.ÜfñÞÆ‰+Ξ~Ú¯[¶A£Å<(Á»n“íU½ú8KÚqe…œýEÇŽcG?‘>|”øç·Z+4ì"©WÛ{™ÝgšsÞÁužq6QÖ™{!í•—~û‘‡Ü…Á-ç܆šç¡†‚˜ás#®ç…Œy¸H"½¤SUôe—™HwMXÄ"|•ØÞH%iÇŸŽòœ…@ $‡@~H¢z5$v¼ýØžˆ’ùf›vX*øX‚¦ø_OÒÍ…˜uU·Û™c–Iþ&š€¥É¦™nÆÙæœpÒ¹¦œuæy§NI¢m=Iƒ!Zç„7^XõXàOg%ƒLÖ×TŸFNÊw›FI§F ”V•‘.F5Ý`÷Å· |H¾•Û„YA«ˆJÞú'®¼îê«®Àî禗œÖêã¨Bäj§ý™d^k‰!&ªYiÃF'Ñ…ö•çmŠÝ¢.¸–Jê©hƒÂÚᜬ=H 0m{¥aû×^^F:]¯Á&Éo¡ýæ ðÀþþÚg¹ûèév×,¹@%û]¢"‰‡€n––÷®d%¨b•MV°Èó<2Á²U²î"Øo•Õn[Ì0¯þ„——‰oÌž–WŒþÜÕÐ>m4ÐHmìÑJ Ýiª[Ëp[-ÒëqÉB"jcO¶+ra:I|›™A)Ó°ŸÆD¶½ ¶i”Woeƒ¡}êmÞÙò‘8Ë‹3’¹ùõ¿'.°á„®xâÿF×ÛjZ'h[AÉì6{g!ª(˜qã·¬º´™úï1×åß°žž3Ä®n.KOŽæêÂ\aË<Ó”¥t3×û6gò\TÀŒ›¼¸ñż¯¶·þ¹¼SÏ/¼âVîlÑblëŽ@u7‰Ñõ9ÊH&5pÆåQÃ[ÆzxÍ~jÕ-üêëúc;«%&Ÿoî©çøxþòŸÈ¿ðý;à(¸Um‹p:™\³@C¥é%< ^—’E¿IS³àí~WBîk'dÉU–©íQ'º›ýFç1BÕp…êêÅA+²éxÊ âù–'DÄÑyÕbÛð䯢öëro©’Ö¢•#ó„ì…òšŽ²…°ªŽv?—ï÷Eº9Ì,£¡Ü ­´-:‘wZR€Ž>ßõ©!ørœ¥¼xD#ˆCü£ù ç@$jì:ìó_•9h`0B«Úöp‡"ðýÉZ£ë—èÙG!I'4£ê`o:—Ã}IÉaZÚÑ‘6ÂüU’ZKKZÑd˦1m–¶¤þ¥Ój‰Ë^òòSŠù㊨/9¹Ï‰ÏÚZµø"J*k’d›W*õ•š +…iC!ß(Ã…¥‘t³[j¾B®é`s*])‰s¯‹5ДœŒg çéGzòdz´ ¹ˆ Zi;¼iæ×i1ð‘t¢ሖ:Óµ®”Ôc]õÊ8ÑRÞ,!.\eí`˜"±Á²ó S í88H"€VÚº”=yÏ–²ô¥ühÇîÇÂŒFÑ34›[°§ïH¡º#9§åI›™l“+©3GâOg¾«‚%ýžßDøN)QT/ÒÒ¶ ÈU_ kW(V¯ŽUhm I÷>‡4uš…‹þL4—A®õ̉ =ÓUB¸fR›/d(6»Í >(”fô¥ ×É(µˆ.Ó²H)–YqžI•g=7ëR¥rÒu|C1ÚDyÍ”„ϼ´°ê“+bQ§Üâæs¢q2o‹¬¨n%:R -lnŒ¥Të<ÊÆõx/uôY ó¨ÕŸvV³Ïͬt9ËRsò–•oe•Œv»ªé4xB5”E-é>ÓòõpH¥®g¯E“èÈ©wmkIoˆ9ÙÞ”±ªK„+½Ë]ú÷–¿ü¯.,à\Ø—.ÚeS°aJ¯?”-¦F¦ØS¾ÐÇlì¥&lLý쯚ukTaGŒZnÆ'‚ÑÛ0ÿþºFçr%¤+t­UI8½­W½Ð…iŽo|œ|n°‚SvÕiNMu t5éA!ûÚfEke+,c¤ÑˆŽñªW.M«åJ^T°.û$÷X(båº ¼¯<¯Ž§]³yÍ ]pNUiÓ5\-© O¿TETi~V´dÄΉÞòñ˜pb{K?S _Au’„¹¢eBÇ—Óù{àVÍÊi²ž¬Ÿ.«§;VQ§sš~™[ý5UŸò»îÜ[}‰«Ð‘ŽVŸªü« …æÖׇ¬M}gªq®±ØÍ:®*-]°ö°¨nŽv›§ gj;4Í€¶Ìh,I§Ⱦ£0Ÿ9þ$ÙÄöX¶  ã}/0Êb9·¼µm„Ñ¥Æ.;v¸KMµ‹»ë¹šÜ#a®¾ÑVí‚úà;np”¯ ¯!CÞå>I’ BLÚoÉŠ»ífÓkí"&z)\~òGmJ@k×Ûñ£Ý¸V–Õ4›(Á&°ÌLóǼæ–¹œ9®"½4‘ƒú:¦žWûŸ–sÒ8Ôpb nÔ¨6ÜÖ,3À=õoEÇá$§§P§õ„}²ÃCõP;ucã„¿ág7{=}Lâ ×ëÍ…ú.H1%“÷uq~rGz©)g¬ÊP‹7ÄQ<þ¼Å ûò¿óÞWšEvPAQQŒw<혗¶ÁÃþÃ1Ö´´Vã(•SËqïŒé­&y‰J_DZí…8½¬q“׌QvDoÛLKyÔÀ/u¨‡OjPßÔÆ~«õ×U÷äšáÄõrë‰\Íýa™¿knš°íݧzåeú&ïr±nìÃw×xÄ «<¼¬å7ŸùËkíÕ“uøÏËm‹{ÌÈx–Lkat@rdz—ngÓ>ºwn]R{úònhH€ÇDõ–~•ùö0•Ö*-#cb³\œw¨Wôw°W‚÷¶U Øp¬6­!Gw›cPØ—g·zIƒNW$¯G‚K^±CL´Æxò!ô¥ƒRcb&raûÅ`þ·ƒs7gs07…3'…U˜s&g¶1î…WØ[RäHDçJ˜WnTT#È&cb`#uûlp¸JõãsmÑ„~ÌVv©…t8%Pˆ!5¶*ó‡öWˆ(¸fl‡ü„Hu¨HƆC‡"†›ƒ1g^MÖ_œ·pá%`xY¶[ŸÈlšr¢øD”5$cªØ^ðóq›füUƒ>x‚„xˆJug‚÷yÄ”*4ôPpƒd{F}‘Ó.´ƒqäx›ÈƒDE‹HNãóM¿¸.$§}`‡Nýv}ìöS¾÷È×ħ|Þx|ß(|âˆ@¨ö{†ö[ìS‰ÜX+ÞUwuެ_·–}Å¥þ §ˆZwæŠqø†r'frxæ§~[lî¸V0Ö\*ÇÎ&µøÌ8‹g×€¡¥MÛF‡nt×}#ez=xþ‘)ä†nçä„íH‘=Š* o§Ô;"î—‚ä2„ñSI_÷t$•M‚‡Y&(‘?”†x ¸‚©w=‰’o4}Òb9*QŒ8ø10TÍØƒB)"¥¤hX톃ªQCµn…tQÈe¬_˜…T¨–W…Xh…lÉ–;'LÙmrözC§Lf–©Ç•iMÕ=g€mÈU×:IYp7wïôˆ¨‡¹ÇH»goŽˆ/‘W ‘@yy‰x˜n·hÏþ燞Éok6AFµ,›ÄP˜HN|¤:…·„ƒÕQ÷"èe«C“±¨;ÉÕ~‘W,‹)E•›i‹˜9”ʃ‹ž'f¤Ø•°‰ro'†z‰“ù¢QÆ(hœq†Xi•ʉ!Î2CÆ•5Y€É؇¬ÓA«˜C½—UÌ7[äŽã˜|ñYŸôyŸá¨|òXD(ö|DF0È”|›a†²¸4xm:é}|%~ *~GØ…x÷KxØ7ªÂŽ|ç›”ùŠ‘äɉœÇ©™F”n٦م•R¢v”—T’Ó”Wð¹E ˆK&o)9›œÈ’¸5‹ù…‘£$P.Ès}n‚­%‚þ>ù™ù¡"ÚRÖe[,蟎ƒë913BzDžÙY^ÓcœÊhžNjn‡¢Ö•Vù•ŽÆ7d¶ùÕ„—p9§oY§ny§kI§À”;QÓ¼øm9(bIƒ^‡JØÈa!æg•’€lø£†éš˜¿šë˜uÖ5I¸¥‰vCš¨Dž"b™´Ç¤¢ ¢M*]鋨£¾Á¢¹*º£ºÖšÞ²Ñù…+I›¹ÈJÂV~¹iе¶š—©ÖŠpHœã7¦!ª¬¥Z0Ì9gRcSâ#©.ÈZPcrªç%crihGªà+³98Vâ¢cFh ¤Û8’å(ŸñjþŸùI¯óY¯ ´ŸôÔŸ•wbšh¦¹l{ÚÕG7`Ê^´ºkûˆ˜Ú¨{j¦‰lÉx§µ»|µÒ‰Ѫ2ˆÌ:ªOj‹(©¢[ÏÙyPä;5†=ÑF½©b¯´u’h*¦‚§«¡¨nNÒ‚¥ˆk–¿¸žJ{p<ù0ß*®J²Lë),9¥ #š?Ú€Ú᪒XW:68^Üš®¡ièÓµÌÊq[i?/k³%Gfì—‚nÚJ-w¶{'§vš§sÛ–t‹§vk4siO~ú¥ª#×Êg'†°gú—„vR;˜æºb ~’*{09.æ˜yh]è9˜›ì„Qîþ™ û±K º…Š{Ù”ª<ëoE¶¸h° ù›Ð–° »®£ä‹¸Š£ Hx¼Z+ƒ›=ËkÁÊyIh€Iø%6œv;ø¹Ëº¼Íêd({«ÑÊ»v&z–‹Œ-k}•b[–Cê\ݹŒÌûºVB¥fûžXi鄺ÿ &‰[ ø®±5¯øy¯öK¿øš¿ó©¯›Å¯¨µË‰¬K TT`Zq¸'˜çE˜ ©«@ø²c—Æ*±;H±§DzŒ¡¿jl–Õ±M;¾¡+Â@Z‘O“zj=®pì¸{’’F¦›&³5›&û£”6›«9zU:{þ©±BêF<'MN»¾þŒé†:)pH»¤#ܼM¬¼Ë]P[‡¼†Ðvµ&Užé{Å[,•ÈázâëÄ0ë›Òz¾>:¡O”E˜›rÇ6\p7r‹·q|·tœ·s¬szÆÿ±Lö<ÿ†ØK¨?µWìé“€‰“Ôø K‡Ä<š zF¹½å¨lågGÇw +UkÆ6ª)º LÂfwªŠüSBvºåù¸òª—ê&"9»Èì¼£çn¶{³9 Q !¾Ú»w¦k Gžä­wÄiƒ¬³,ÊÊ,ÆNú¬Ð ='{s¶ž.ü‘|š›]Êz,Æh Åäk±/™Hœìjê+k±Z-Zö³T$RŒ*¯îlþ¯ø{¿ï\¿ÅÇ¿÷ä¿j|T®‹Åñ(“†l{u°Û·›)kŽÜÈ K½ý÷ÊŠE¹CëŽëçºú´ÎÁ±1ä±ËìÍO\<# l'Í&)©£3¨úWÂ@ëv팦µµ:µ{»8«£HÒ£Æ.ç4Äî‹0ê9ÉŒ|J<áÌÌ-®QÊÒSŒšA\³sÅÏ;£©aw{açÅ«ªÏa¬ÑKu›»x¦.Æj ÂÑøå¶U·½X·w\ÖzZÇf]·{ËY ½ [x±3QÍP„,‡ÿ ¾Oç‡êü”|ÐŽë°.ë|ýʘ]wÁ)bí›a—»¡‡Õ¹‚Â@ÙT]”lUʟɈ¡þšº¸ã1¬Ë|³ŠŠIg–ÿôš´kË/}ÚööÛ¿Ü À[¬’ÉÁGZ“'<É»Ñ=Ù©…´½W¹Ôú9BÒ×,ŠÙlžÈxÛc<Α>ú1žÌÝ|ÉKÄÖG¼ÇÒò+£ñ¼Ýó¬¿Ü ÏólÏ$ØT ÀÚý#¬|™ÐÐ:%Ð)ZkÛÀ–íÀࡤXÁy<±ÕGÌÄšl1éÁ Â?­Û’-²%yÅÚ†ÂeLz”»Éª¥L0|à¡mÒ‡ ·±…ÃæÒ;¼áM¦h˜ÝÔD¹×Aj6¤½³Z=]á¾â¸ {Cm”A”K¬” §—¡]vÜP¶SÝÄúgxþBˆÕbv[ œLvŽd™»Lø¶!=Ör|Öv,åiådm‘Å+}+#o=M×˲‚,8u­nu†\$BhÃÀŒû×lNäQ®æv‡muç\¨½ÛÉŽ­ÞžÛ-.‘¤|B¦š×™B¾²YÚÊ|%«‹~WLÍÄÓœŽŽË·Ûá ×ËÛÚ½F„^­ºbI¼¿ƒÌÔ~^ê;æÌ½ ͽŒ¼µ)!×î~:Þ­p´Ë›cKÙ¡Á³ä鯮¾7Í1¦¹ø¶Î©ÌLò ÞÊNÏÝìÌ~j—Ú¿ämÔälM´·^̶6݇.Ú| ôͰ ˆÒKlùmØOئTÕþéyN-Íþç}~ꬾ]îi nÖ»²ÕYÃ|Þó+›¶Î]¶¬áOé:=pÎØ!&ÄîsNT¤¢ ê;˜â—ï¦NêÐõâ^w”¼À6ŠÞJ--žãQùT~ ¶Ù®Ç˜©±»¿}¨Y¶GÞº/jÞIoœ‰S~å>oå@ÖT^²yÌs\x߃±Âª°ŽÈÙΉú=‹zñß¾6mî×nNàõQ}ÝL½¶m˜Ø¸.2ž|žòÎâ¿v¾nÙƒ>Ø•|Ô€víRÚÁL’Û¶€~7Y’~ð:Üê\Œd<äªé‘'S†Óìl¬g¼'eÛ*ñ¯ñ°ü¼©þ¾e¼;­Q1z/DÜHmÜ'?÷‹Ñ#ŽöI7‡?özž“)»UÅuØížèøì²ïÝÍþݳïìi^Ùã­ŽåíëX³Ê#ŸµQ2æÉ¼íå,™Úßà>ßÌ¡,„HofŒ©û}É=–a,.ùóîýE¢­à«Ž²ÌMïï }néÅEx¯‚H¾}ð!ÿ£g"ÉíÞ†¿.æÛè|Ä‘ÚÀ B38°Ðð9<8ð¡D„'¼Hñ`Fˆ-~ô#È‘"5–DyReÇ”,Wr„Iò¥L—5cFLˆòáÅ2{&ƒVDèÇž8Gòt™“ R M¶°þaM—7UfTjÕ&Mª/f¥‰ÕdÕ°eÇjݺtìÁ¨CæÌ™1¦\³*ÁÒ¨6oܽWM…ˆ4‘T¢gY üzXqbÆj\ìX2äÇ^'[¦|±æÈ™=c½ù³èЊ’lXu^¡Ežvœ6eÏÄ@›UÈ/\™|uV4™ð!Ø‘ÂS‹nôtðâËë…ù¹ôèÀ£ãÕû¨½¡½Ÿ'§IÜ/E¥‘Óž^;ÙÕA,‚X^üÌö²é·D›¿î}þöýë¯Àß8¢J)›k¨Öòš¨<Žlé$Ûœ‚Š0ëf3Í.ÃÃ/Ãÿc鼿| ±D¤N<*EŠPﳌþj½õŽsÑCßT\i-öòº·ê ” ·=â°Ã÷ñH%d²?DòIA£QDƒrë‰b#ÍJéðJæ6‚¤¢kF§³ïÉØD°É¤Ú“2Î(Ó“IÁîèt3I ×2®#ßnÜl͇$ï ©² ¼øÚT´Që5.RF¥TÒB/]SH'µ4SO7Õ´RN•[KÎítT÷Ûr¬¦^‹Š¡}LéFç#m>꺺UU-—+òBa!üÑWbw1'.×w}0Ôlµ¤mq¦X’J]Mu\(—7Ü9ÉÕs& …öÀ` ͲÌOå‘· …”Š/þì}“I~ýu_à^÷ÙE\af·ßã´Ã2Ulý£T0<#¤«ƒ«]YYV™?[Y‹÷â­Ì<Z.WU)ÎÄ™ÃCž‹³Êœýº³ÒÂ&Ûk³Gì³Ç^[m´õhi)ÇÌÒG¢çf/Lðe(c4ÅÂÓ==õËcD‡UpÂEMÆǶUˆôº’kšO`ŸqÔÑïš³ÅÜÐ÷—:锑F½èrW?]uÙF.^Á“£ùêÏÛ ÉðW+”õpm•Ûî¡%‹þÃ᫜¸ø¬—g—aä·yY[¡k]½_ÅS Öp°bE [Aßu9uÖËwýóMÇ~Ú›û£Ûµë}3fk—»wL݈ zpþÔ4Xúœ64ö°YÊH휆–tm/{„ÂË™-æåf*¾ûM§@5/ Š*Tá¨>(B’pƒ'ô` Ñ„ÁÕý$b…¡Ö~4¦3hìî)=ëKu¶'¯Òq†OÎé’‡§¡îÉ®XŽ3¢Ñp¿×¬‡7• ÝĤÀê(Ñ9XëAÂ-¸éЀ4_ëÖFõ¥ÌbœƒÜ»˜8?ªåXèÑˆÞø†’ŒYV´cðfÇ9€ª óùþ>Ðq$Ü‘ô(fœ3⃺Ù;²=琢0°käÁ¸IMvRŒŸ,#6‡<­¸r¹Ë!);‚/GPSä·ÐɰžT_%'"½Fu”Í&x­ëŒ(fƒéçŽç6¶¡­lÎl[Ú¤ùÌfV“™×œf4»È5Ó­‘YÁl’AÄ’? îæo½œÃJæ¹Ô3‰Šãä8Ï#Q`­¾³ZBïr}bSIÕN)îg‹¤V(¿ˆË…‚²¡ mجŒø¯Šä“x-yc‹vÆ»©Œ²WúìP°–y;/ò¯yÉ«ã c¶Ò%^ò£`H·9E{*³f¼’Ã>6Ïþ ™”]²$ãC…T¢rDÕó©—r¤¦qOlJµ§õGGŸÊ ¤M à”4=2´¨;­Î!ïTSа¤#ÒXZïwǃ•HYÉŒ!rRˆÂŽÐ®*Ä+]M8W¾Ö5¯}mñâúË™½+EKŽ[i!Qž“¬4Õ'ùR9IBÊ“ˆ¤'î2;Dì±e£ýΜ¶¦NܦŠ]Gm“t ößãZNYМŽ2ºg›É©!Q‹~‹jË},q†Dª.^n`%iãûPE°­oÿÜœè6;7YÙŽ|U-Ñ“^+Uâ@á¸+ñF‡¼ô•qº5NeCs¼›£ô£ò,º±{N)ÕóTÄ,lÿY~Þ•l{6½ñÕ=1%rîì…{íÅküÛs&øp¶fò o˜Ä6:ÒAœô½éJÛ6‰>Kx+ÏQBû˜pó7Çæ<8¦±o&m°oVþÚœEûôê´å«¦È@¿xw q“ë N¦¹¹õÞñsÕÊ]2íØŽç(Znê¯Iù™çß2cXñóm¶šE]ðéüy SVS³Õ¾ “uJ>«Z«uZqéü™›1÷xÞù¾wu;þ3¿Î÷üÔÝÁ-n]Nê%SÂç-YO.Z©ç5¿V{©XÕõd{›,3Œq&%f·êÚú·ž5®k}î_?×w}<'M©ðT·â¬Ì¯+üº£¾4̦¬OÉžm³ÞþàfZoýËÌÂo^lÙô*š0ÿ3ŒÖ’:Øê»ÔSÀdÀÛ:½ú{·b#£88<§H›ªIË#Æsþµc7>ª‹€£´ #$ËÁß¿D"ÀÑ.Áá.£ñ9 J1>c¾‹ûóR½Ö¾ÜAø9ç¹Á›8Ã+èbS?þ"-Þ«.šA÷³™ãÁË) Ô)êµs"¦<ƒ°Õrq» n’¿¥#Ã:§cº4,C4$C©K.×A1%›<«+‰{Ë=®S¶C6Òa§!¬¾›±úÄã¬Ü‚Œ‘£¤Lë?U‹;ɽbŠA—šŽ»ÛìÁK\½L¤­¿Ä,;>ò ¿BT²ƒH<‚¬+,º4 E(±I$ÁÊ+ÁXl>—½Õú¼Îs$pr¾-Ì1Ò›Ó#:(ÔÄ$Æ)þ, Dƒ½±B±«5«7µÐºýi0 c¿5SÊ4*Ac”¹ú+¬;ås°‡[«? S+²U›¾`ó¾íkGíƒÇîþw”Çï@vü™øG1¿ABR•=¼Fö[6¼’SEhK»û#ÄgÃ]Ò¼Ñû¿­*((Š+œRÆ…C qã¢Ë¨ÆaäÆl@—ù@C¤?Yy¹:BT";$“|Û#Ïû@~;<ð ˜i´4ŒEXÄ¢Ø@ÄÞÛ§LzÁ磟TꜶ©š’ ,Æ‘ÔAl@÷Zµ ü5æÚÉæP¬ôc,Û[Bæ³Æ•³â>¨DÅñ­ÇÒ9³*Óš¸¶¼©þŠÄd ÃÃû©5<û|º¼TC3ÔK»ü07üÊÃZÆ+ú­©\̶RBïâJ#tE• DùxÊÓlJLT7NlH}ƒ´ª|%j»£Ü/®©:ÅÆ›Ågt´ÑÔIžì͈Ϻ¶tl˜:Ã,×@¼ÇSôE0áDM‘TÍÔT(d¤Ø‹HDN$³7Ü{Iœ\8̪ƒì´mtÊnÌäJ 4ôÎYLGy« ¢¾FrÇyÔO{ÌOþŒGzÐß[¨„!|l»/ÓÊ0;¶Êñ ÷+H†“Žî\ÈÈJΤlÍA,þ7 ‹·¶ã?Ф0‹´’Ó3Þ\¸­0@îœÎô¤N²$I@kÍLI9t£ÄéÄÔÀ?$³ì*“7ä28»ÊW|³žŒ¿Á;ÑÆj8Ü,µÓrÒ#“HB ™†àDlÑ­Î+¥,ªÅJ¬ Z:Büâ™Ú$­ñ\>¡Í÷Ô )dQ¥¹˜Q´„Iô|°Œ\S^ G‚ôLE¾ÜK6T¿ T¼,Ô¿ôÈ7dobÆ9 À8ϾQL‚ÔCµÒy¤ù3¼ç´Ì %+ˆKPcP·[ Ë £ÔsD t¤Æþ+Í+sQ,Uëì@êóTO9~\Dfl‰RËÛ”IáþIÅÃ’¥V\³ß,ÒàäEk{äSN u¸:]+ÈÃS¤D;?cˆÖÐÖmåÖnõÖo×p×q%×r5×sE×tU×ueWråP:¬ ¨:?•V4KøbN6U–{Ó(¬ÑÂUü»OÒÒ¢¼2ŽIÕùt®…h׆u؇…؈•؉¥Øu ØjRm£Mc È}Cæ€ÂoÂEC4NÅPOÅ£ ŠCÈ~jP-PÔ=/ Þ*{àDºÙŠœÝYŸÚŸÚ %Ú¡5Ú¢EÚ£UÚ¤eÚ¥uÚ¦…Ú§•Ú¨¥ZŸíYž½ZµÚ£%ÚœµÚfeÎÔê±ñpIIFEíQtÍþ-¼I1ü/"…[ÊkÏŸlBTJ5­ª‘»ó»PÞêÚŸ¥Ú©ÜÀ%ÜÁ5ÜÂEÜÃUÜÄý[ mÜ› \žÝÚŠýVRLP•ãJã$Oë"aôØöÌÒijdL·}ÛµìÂ|å'•}Ù“†€ÝØ•ÝÙ¥ÝÚµÝÛÅÝÜÕÝÝåÝÞõÝßÞàÞá%Þâµ]×H HMÌíú\¦¼ªKUTšLH„5Ù¾µÐ”U}ÔLÇüW¸ÓìýÑÖíÊöŠ÷`ˆE8ßô5ßõE_öUßö…ß÷•_÷¥ßø­ßùµßüÅßý½ßþÕ_ÿåßÿà&`6à>`ØEßö]ÎÝÿÝß±*ÅÏüþTUT[5‹b•¼|LÖ¸ÍΟ[Ù<Α ^T+ƒŒÒ¤Ü:¨€•fa-‹·na†´[ÆáÖaæáöaââîá &ââFâ#fá&vá'vâŽb(Žd°â+† ,Öb-~Š,îb+îâ0^–²¥*ñ\­ÍåàìÈF[BÏÐõ×ßH\ÝëÌ“`Õ'4š%8õÃ'_Ñ?ä@äA&äB6äCFäD>änAY’c ?Î FVdB¦œ…PJÝMïYѬK@TÈÊn£¢¥2aãL‹ƒ¢a0Æá„XþâYnbZ¾b[Öå,¾å^þÞåZæå_Îå`&f`6æa>f\Vf_.fdvæeæ[~C„Æj† –f!‘eYfá›0ô@ƒçÔç-#ãÉ\tMšT€ ÒmDV~gÍÒ2ج[R¡O&Åç„ÅÆUÅckå, F&hÌ4èGFè>Nè1]èiVè‡fhˆv舦艶è‚nhŒ–h®hŽžèŽd‡îæSŒ–ä‘éIv>Z žàÌ¥F4ΘÓW]¨ÔÀ‰Hg5]—»ÓØAŒõ?ëÑ/øÀ Fê>Nê’Vê¦fê§&é¨é©éª^j©¶j§Æê«¦j®Îj¨îjˆ¾ê>h¨~äþ°FiY®–€bëˆSŽS"ãk^èYé•Ì!eëEÙ9ÌÌQ²R_„Ú[-GVÖ `„FžU-uìõJˆ ƒˆe†ö¾‹PÕ½—S_µÍ ¾³¾Çiu=¥š¼x–[›„ØæÚó\Í¡fåEçÁþÈ,dËê¶é{~ìñI$åi^ãׂÕ=½TïeAßQ¼d7nì~-0üÄʵ©½Ùƒäʵ´È¼T±äïíLµsP 5×å÷»ÞFÞë5›S!kÙSÃk1Ñ_þÖ Ìá‚$ }lö–ÕÖm‘º 6 ãæWÊbÖ#T^ÝKgµÉSm°>šçœÒÕ–ñËd‹‹áÊç`µÑL²µÞ¡s$íÏ!ÿÏý$òz<ò®Ëà$BîÆÌ®ÒF„ÚÐ"péËêÓÍÐ3uBúiî¶ñöÖ@Y&åÒ¥KŸöS›9a†£Ù˜1@]ÔE §Õ8W//Á)cÛ¥"ŽLب£âÄ'éžTÔKe?G™LšÞÉìÔOt²g¾%l—õÌ&uËvƒ Ä– /7ì¾ðö†ó6†³ÓÕ=ÞlDÁür”äŽ*/SŽõ=ìm ö(s±ó4–qÕFmÇJ°âþlÕ©!ê`åÅ<µJ1Ù­³ô`î¾îáNvd?vy-“ºó¢ÀšEFѸó’õµ›ýó½™*§n™þ¯%ÿ:6ÆòO݇a"é4­cJ¶~¶ã'5RéKo˜îô —óõ*¿M‡.O‹¨K½rźÖPuŽºdAÿX ¯Æ[ô©Ö]×k g¤Z|ØWš]6ÚO¦iØ‹©é§q=÷€rÛFªËÏ̶Ú}ó]¯Ö\·½÷m¡Ö 8Ý‚þŽ0ãž ÞŸJ¿^—¨æ¯!,™»¶ùå ºÒ¤îùé¢o šIÛ¹.:z!¦X-ÓŸ‰÷çµn["‰„º+)Ûr­å‘|0”gû½¸ò3v¤êýn7õ‰[ßY¤!•ÄñóË«7÷ðƒlv£Ô¾ãŒ†<ñàg¯–ZºµHÍíôn©ùÇ<ôlýï-4[hæ?záoøáðüç2‰1°~ \ #Á æ¼ßH È é,„–ž¤EµÑ…P0qÚe\g´¤Ù©…W; Ü,Ç5ÄYiu[[£÷=Ö0H;ì!!¤‡è­†Flœ e)·gþl«óá“H8ÇI{CÜL~âtÄÏ ñp–Ûb…è=¥e-¨rRÙœ·Ã5‚ñq}ƒ¢“øÃ6’Ïkëž›‡Ç=²ñŽs4"”´è"ÅL­t,”ڇʣ­ÆROÓáëB³=%r‘ŠSÛûèSÃk­¨ØŠ‘íîÃ.ƒXì^˜JH>xÊ'¡0•#¢?ÙÉHænwš™M&ô;¥™Kd…ŠbÓ9úM-~&£Ÿâ¼HIçœë—ÇÔ¡„‚¨FV”PŽ^1=%èA3šÒ;¡ðhú¼)ˆØr)w¢er’è%¯g(#ên¨ƒ`ï츺šŽÓ¨÷zêõªçE©R5ª„š£aÂ%È›F„ròŽ'å)5=)r„fx°¦EED²­*²©G\©£ŒL²ž)¨@ØZ­~äv©œ¡¡×ƒÂ[„Ua\'#×ÇLR°a«ü #¤µ5£ÃäJØb׃ØsŒ ’ìg7ÚOxt¶)Ùm.5NÊòõ­ºkmhKš'ÓÅ–1]}Ý"s{¢Ýò‰·ºþí-pIS¦²uÝ!¡Öi5ÍjΕ“êéÖß–Ï ¶é]HPç:™.ñ=q’©gdzÐ 9Òœq$ATU§ß—³ƒ­[9Ùç–Ö»÷ì}dj^Ó w¶‚ ÛÁ¥)Ër–®“ wA´ÜÆp¨àò©[œt`Ð4w,tÚ‚73Ëä&ö¼¦ÚhE%b×"‰K¦–ÖvP^ýpGR4;±ÖTv¢d`|[óÖ)#2]¬2«üÞ×6ÜkR]˜Œ¼2‡Ö}ÒA{,ý²èÉI“«)3;å-ã);IÎîdŒ¼/b6f{C.[‚C,˜ƒ¢5ÌUÞ2)G9Ôn‰‰½þQ†µ#ÝݽyvIVç!£åÉùHF¬†fÑ¡ èE+ºÑêd­Eü»v²èÏ"¬ñ›=ž@Wjæ³&Ù¢ˆ bÔ  ¯H§œjƒ²•¢¬^i}Ç6j_Z—¤àqµªMÍ]‹®”¢l5@¥ËY(£=¬ª7ëë)[”£Ätiœ’Y"+»Ô Å5³õškã5ÛOcˆÂùí²¦¹¶5« jWlcûÕ­'^›ü`3RNÂÜi±‹IÜåH·5©Ò‚š!9ÜçŽØQ–Aïd’bA­Ô4í‡p÷™Zò––ÑJÉå¼ê¯2muÇ3Š×YrC דڙ!çU¼-÷ÌþÈ­×ÍÆ!Mnl‚¥Íê–oYÚ"7„¨ò‚H4\0o·©óê^ž?¹Û5ß9«qIfRj’È!¢ùÏy®Ù»›Ëõ9ÓÁ{²3µ(ëtùj´ݶÓú³áNéÞñ´îx¾{ŒñÎÁ¼ó}ïnï­¤cÙvžÂõ;¯õré*=¹¿èµÚ­-Üð› O›»D~7àÚÛ]´Tç½Ôü¬›ß»ný°“HF;Ê˜È è —ú“aïr1 q0â.ý¬3RõXó[/ýʃo›Á5Sg!0*KŽù"+}6ÜýT×kHdЉ§Œ*Åb›gN_ØÄÞ]yn5‰ß¿ÚþÑï\¿54 /¢IÛ~þÆ»UÏ¡4‡ÝþiÓiüÛÿE¶`}]HáZèÑžÍ9‰Ct›¡g¦ÀÌ= ÇiVÇ dÝ\„—`Œšv´ ™«IÛl€`Ha™­^´ÍœãàÿmܘT±Í†œ%—®YÏyÝ€´Ð5àá¼` Jà_!€Ä•Ý–œ]À½™ÃeÚŒ šýYMŠ`šü)×ÁS¦Ž&M Ñçýε¤Ór (qáÙVâ}ÓÃÕ–’%Oð9Dï̺­œ¨žñ cXÖB]ìi~=Ÿ³}ÐíY×ÅáêxàEÌÞ“\ŠDF1åYÚ õq„UÎ¥yß[Esõ›Y˜¾MKy<d^!qaáH:a4¢üѤ‚)æ+†•âÙIœþ‘$‡9èÏÍÐܰ ]E[úÄQ3yÍf¤–“UR¥Ñ÷DÓe ƳlŽÝÄÕQ¹Ò RÝ.Î31“jB2e—!4ÐY„¡] !×Ûuš,>×u|™§UæF*!0Ч/Þ¤yþÖ¤~DÅ:­Ý R¾…磚L>#ešßo&ÐTE׬€ÞÌø¨ŒÚH^ "Œª¨’»ì¦ 1èsú¸Su1§ã$Øÿ ç4Á%,yÑnn‘ø8Å\K+’Dö¦›­ß,¦I}¦H–aaÒbI¢$Išä‹õWyöK1ªèK^gÂ墌}¦áþ-˜ÆÁ‘9 aQi¡œÆdp‚ÆùÚª *çu-g%¡RàÔWk&içpœ*6(+uZÔDéý½S¥èi2Nt—Er €Ô©Þ)žæi|di¾m!gºÐÚµ3îÕb^Ü„¹H€ JCuX¾KuDþ­)¡]¹„ÄáÏC¨—Z‘O+eßTcUQÆŒ¸§×Pœl‰ˆ†ªã“¶¨c¦SÀpBðKõ ¦žæª®î*¯êÇÂ9Æ1Šg2ò(N%Œ±Ÿ}â¤z ‰gñ¦ñ–¢)³¦}ÖåG˜œHìh.jšimK ª£š)Md%Ö¸²q dÁ(þÕ'ý™†¦&–EÇrŽ<TÁ_ОLÖ­oÑŠ¿`pS¯áˆØÉ”›ªûMœs±k†VRÙL>åÓ¿AÜpìÏaà°À̰ ÿLýÀ ¦à°«ÏMëËÀø0ÍÐ/kç0ËðÍÐ4ñ˰¤ä“#Œ»ŒsñGqŒvo A•ÃdLºöžÅÇ$qǨ±ÄPŒÂı¿1c [PŒ¦äñËqóqœ˜KÏÈŒ¶ÖìÙNj›…fþ‰ÙØ}ªáiŠ—¾ÆŠµ©jD²–Âlh`2lÌ’k|a¥ø'ÃÆ(£¸TpÀX,„~h1Ê¥dMUÕQ6ÕP“é~Þr,'U‚Š-Çò2ìmp2ç© #§íU23føRlv”±¬Æ1–¡*À…$Dñp¥:À},£Þkó|l³7cä5›3ÕÝR;c ܽé“;ó›³¹Ðê9ïìÑТ“j­MÜÌ€2.[ú$4øÐq,å²Uô~®âö8¨C¯Eç“ û2¥1Ðʲ¶ôáJ3e3týÛ|º'Õ_-~«$¿´)×ìh€2Ó–þÜ™Æ2ãiïN§F%·†ŒL§Ô/6‘i-#é,5É+»f5EuQwQiÑQ_µ5 Îmv¬Kß´1û¨ËNŽ.&Ü.®0nD (µ.W-ã/W.Òâou’Hãì·.’ ϵ&¦nŨo&^Ã,¨õ5ÕR×õÍj •h¨ò¢Ff¸AƒA?ò¢2“32ÖN¦fÓVÔªÏÉhg?^75D74ÚnFeCóG7¬b¢*Ú’4G"nQ˜#ÏÖ~}Õs%2‘Z«eò6±ž¤âm'$12¾XHV™n›Ÿ#Ñ(±zj*ê¹Zš‘X…Q‹ÉZd÷É{Np‹þ¢!KA·‘I7³ñ©Ñœ÷®Ó}”¶»TF¡÷Jñ0‡•æ Þæ¶EV©A-Ÿírþɨ©NXÔ0žÎèr+šø®tzÞ,ïÌã:l^'¸w/8jg!L{òLvïá\Z¥•礶„wëÖ2¸‹0ö´®Ó=aÄ’fÇR–,µöè'uCk–åõà:ÖhÌ:XÖ{­£DèX0‚¿hY 2D|}›¿ÅØGÇm»‚–y¸¶Énß~»ð».˜£¾ì÷)­lǧ«&îyvæŸjùÞõWŠ~$Ô jùönÝöøJ¸3¶9¥= j±¬cY‰æy+Þq†ê=ËPOXž-¸8A<µÒ5d‘…¤þ¥áøBº$2]ïX‰d™“ícðùl0nËgœ£Ð³‚·òØlošÒ„_¢cyµ¦¨ZÃ0øz•ß™M®F¬4H¢ß2?moãú‹¯_†BÔ†.”àc~/<±wgÐÛeùx’L³°×[(Ôžë±2²ûŸf&•ý¸™&CF‹Ù‘ç`9S!`¶ïY…ôFjøŽæKò´2k¸[Y†÷û6¹÷žu©wy«‚ó#o9kßÉãqöH·±ášqäÿÈÌ‘”$.Û̯Ú\†7/x=™‰Oü­áÚØ9³m»+"ë[E9Žw'FªSæ¨m÷Â:Á§p¿Ó5¤‰su“§KFø†“úÓÿâÓÊmw«¤ØŸ5 «ä1—QÀ(̰CÖéc> Ö1ôa˜É›°gIÆ uÆ{|É~‹[ÑØ ;³mz?ã;þÝ×1Æ V~>Ža ÝŠ;@6_76Ž—œaxÄ*rû1òXÇ6¾m¼{ÛozÓÿö€§>ŒÇ9î·9Máa3óæ¶¢‹5iÆø£Ù»œ÷y£hÛFDâ´Ý86zêAûA uZôT²'>ÉþÉg<þþŽ/„“{ÃÞé‰Ùùë` b¼Î©CÂ\<†"—µ?—UõZmâËåý£ò»âæ4@àƒ6 4$˜¨`Bƒ :|˜P¢Ãƒ"T8°¢ÂŒ!jÜØcÄ?‚´øPäB“Ð>JdXÒ%Ä•!Þ”²%L,UºÌY³çDž>i=thP )‘Ú@²V‹¦ÈPA«í¬v%(ÖÕ°V¡%S4ö*´®É ÀªÕjU‚.€@ï^ªu©N åÝdh!˜u«Ø‚oݶíÊP­!®h¡Ý:ð²Ûµž-[N›x.ZÇW×rUM–³¢ÕVþ3´¼:m\«öŠ„]Í•mXɪÓní W1EŸEwÆä™ò s¡F•¦„ µcAç@±_Ÿ®1ivîÇB*PúIòÅ+7.ÞøÎ›áÑÿÜÈóæõ£MO.my¤xýã¤n¾ÿîÃn)ÀxbL­¨"ÛÊ¬Í äL²àbãÌ*YL«Á‚K†°à{ª½DëöN$n.Ù‚(Ç kP4 Y 2×DƒM¡ ƒ†±´ÖúȲ½ŠìÅàC ÉàlóqÃÏz‹p­¡Ë,×"mÀî ûï"œò{i©•ÚSŠA ëI'óën'¿Ôï=8Óì’Në°#©M“ÈüŽ?ïåí{ûóç–þ¿”®á%oŸÜ÷ßYœb+^âd2°µåQ–K› ½õ=÷Ñ0MÛÁ^<å¶/铈ë´Óù MG.j›…Šb Š'ž“ ns\¥´" óÑ)#häßðIÁ7pI¥ÝþÌ„È^²/Û¹#]ü6iþð¤¿|¥™.Š€Y²r¦Q©›âvÎ{²2_ã;IÛl¸<$¢pl—ì¤))Ï„ ´–âLçñöVSÅ‹›±WQÚʧ*Ì/£›à›^˜Ê/™î +óQˌ钅¢ó“Yê‰Ége‰ Hÿ&Ã>™­ û‹—›‰Äá=¡EDCÁþ5P(îPm®Dl—òºII6±½iI0ÛNK•S|[)Á¤ÓãuK®m=lCñ¦PîÕiq£Ô∔Q¾)•@ž… F7t.tžÇ>+QÑw˜ÊÓZU›Ð„ÆI†ÏÓ²+oÍ-ûÂ7R‡$©‰ó$Ûž÷Sº 5®îdœ£&é¾sÚ¨[íiV‘ê.Æú3½u=¯RéÃÕ²ð¨ó…nÂöÉVÀ°ƒqILbü`ÇC&ð <`?‹À pƒ á/XÁþÕƒ+œa Á–0€\Í"8ÁVð‰KLbCXÄžp‡ â+XŠ5â)•¾uî4µ ç eÉþ]}éÍœý*h;çudU®M@Ø 6³iä|â8©_[(— D%Û3RŽËȈ?ìᓸÂa&ñbflb5kÅf0VÌQ‰KüâPÖ(îØÔu©œÜ»å‰°·Z½:„oh¨Üªü½I­ï½¤ºT¬n/½™¦â|±¬iâ-V¼Ñ%~½’Ž"Øè˯]^Qø„{•å=ÏP~muúÔz»å™+ÔÕ]Þ¬ÃóÉSÄzÚV(õ‡XÅ™*nTÊ•kW6Má‹o×wˆñÓ{*<âÌ!›Ø§BÚݽ²”Ã;¯Ì66Ý‹·íe×-Z‚ÛÉ‘•¹iït¸;5¹ñ!Õrß‘œ“$<+Mo/ÄëêqI:<½½L½êÞzSç×õ±·¯¹j»R£?š­Š„¹…ÜãÅ’›^ÎË/âùÒËËëôÌ¿¹x7¯T¾B_9Êã9qojWg<£_:nŠ€tÄš™°/ßøMÉ Š‚ˆÉú)óÊçª ¡ Œò%èÊ;:pnÁH7ìü MAFE: MH Alias File Editor

MAFE: MH Alias File Editor

by Andrew Billyard (andrew_billyard@alumni.REMOVETHISBIT.uwaterloo.ca)

  1. Introduction
  2. Installation
  3. Terminology
  4. Usage
  5. Issues


Introduction

MAFE is a Perl+Tk utility which manipulates the nmh alias file(s). It can add email aliases, delete them and change them. It is similar in style to aliases.tcl by Brent Welch and Scott Stanton in the standard exmh package, but has a little more functionality. Unfortunately, my TCL+TK knowledge is limited and it would have taken me too long to learn the language to do what I wanted to do, so I've used what I know: Perl. However, if anyone wishes to convert this to Tcl, they are most welcome. This is not meant to critize aliases.tcl by any means. Indeed, aliases.tcl is much faster than mafe and is native to exmh (whereas mafe needs to be called via exec, see below).

mafe uses two features of nmh alias file(s) which is not currently exploited in the exmh alias editor:

  1. nmh can allow for several alias files, which are all specified on one line in .mh_profile, namely,
       AliasFile: .mh_aliases_research   .mh_aliases_friends   .mh_aliases_family
  2. nmh alias files can the format
       friends: All-Friends:, friend1@b.com, friend2@c.edu, ... friend@z.ca, ;
    (note the semicolon at the end as well as the comma usage) so that specifying friends in the To: field will result in the recipients receiving the mail with To: All-Friends; in the header rather than the entire list of emails.


Terminology

As mentioned above, the nmh file can take one of two basic forms:
1:name: {list}
2:name: tag:, {list}, ;
where {list} is a comma separated list of email addresses or other aliases defined later in the file. This help file makes use of the following terminology:

  • Alias: An alias will be defined as any line in the alias file in the form of line 1.
  • Alias name: The name portion of the alias line.
  • Distribution: A distribution will be defined as any line in the alias file in the form of line 2.
  • Distribution name: The name portion of the alias line.
  • Tag Any word(s) found in the tag location of a Distribution line (line 2). The tag is what the recipients of the email will see in the To: field.
  • Address Any words found in the comma separated list of both the Alias and Distribution lines. Note that Address may be anther Alias/Distribution found later in the alias file as well as email addresses.


Installation

Requirements: mafe requires the Perl::Tk modules.

Presently, there is no "installation" procedure (such as compiling or rpm-ing). Simply place uncompress the mafe tar file into a directory seen by the PATH variable. Mafe also comes with script called exmhmail (which should also be visible to the PATH environment) which launches a compose session in exmh.

To add mafe to exmh, add the following to the beginning of exmh-defaults
*Main.addr.text: Address...
*Main.addr.m.entrylist: alias alias2 addr
*Main.addr.m.l_alias: MH Aliases
*Main.addr.m.c_alias: Aliases_Pref
*Main.addr.m.l_alias2: MH Alias File Editor (MAFE)
*Main.addr.m.c_alias2: exec /path to mafe/mafe \$address &
*Main.addr.m.l_addr: Address Book
*Main.addr.m.c_addr: Addr_Browse


Usage

The program mafe can be called from within exmh (as described above) or can be called on its own via
  mafe address where address will appear in the Addresses' Entry Box(see below).

When it first starts, mafe first reads $HOME/.exmh/exmh-defaults to obtain which fonts are used by exmh. Next, it reads the file $HOME/.mh_profile and looks for the alias file names given in the line starting with AliasFile:. It then proceeds to open the first alias file mentioned on that line.

Layout

A screen shot of mafe is given below.


In the upper right corner are several buttons whose meaning is pretty much self-explanatory.

The name of the nmh alias file is displayed at the upper left.

If there are more than one nmh alias (as specified in .mh_profile) then the label is replaced with a pull down combo-box to switch between different files. Note: if a change has been made to an alias file and has not been saved, then either selecting a different alias file or clicking the Dismiss dismiss button will result in the user to be prompted to save the file first.

Left Side: On the left hand side of the window there are two nearly-identical units above one another. Each unit contains: a list box, an entry box and a row of buttons. With the exception of the last button in each set, all look the same. The upper unit is reserved for aliases (as defined in the Introduction) while the lower unit is reserved for the distributions (again, as defined in the Introduction).
Alias unit (upper). Distribution unit (lower).

  1. List Box: This box will display all the aliases/distributions defined in the alias file. Clicking a particular alias/distribution in this box will list all of the associated addresses in the list box on the right hand side (see below).
  2. Entry Box: Any changes to be made to an alias or distribution is to be put into the entry box.
  3. Buttons:
    1. Comp: If a particular item in the list box is selected and the Comp button is pressed, mafe launches a compose sedit window from within exmh. The To: field will be filled in with the List Box's selection.
    2. Insert: Inserts whatever is in the Entry Box (if not empty) into the List Box and generates a new alias/distribution. Any addresses to be added will be done on the right hand frame (see below).
    3. Change: If an entry is selected in the List Box and the Entry Box is not empty, the two values will be swapped.
    4. Delete: Delete the selection in the List Box.
    5. Alias or Distro: If the selection is a distribution, it (and its addresses) will be moved to the Alias unit. Similarly for aliases. However, distributions require an addition distribution tag (see Introduction) and the default value of "Undisclosed Recipients" will be used. This value can be changed in the right hand frame (see below).

Right Side Frame: In this frame, changes can be made to the addresses belonging to the selected alias/distribution.

  1. Distro. Tag Entry Box: This box remains inactive if an alias is selected. If a distribution is selected, this box becomes active and displays the distribution's tag.
  2. Set Button: If the user changes the distribution's tag (in the Entry Box), this button will become active. Click to permanently change the distribution's tag.
  3. List Box: Once an alias/distribution is selected on the left side, its addresses will be displayed in this box.
  4. Entry Box: Any changes to be made to an address is to be put into the entry box.
  5. Buttons:
    1. Insert: Adds whatever is in the Entry Box (if not empty) to the list of addresses in the List Box.
    2. Change: If an entry is selected in the List Box and the Entry Box is not empty, the two values will be swapped.
    3. Delete: Delete the selection in the List Box.
    4. Expand: If a particular address is selected and it is an alias/distribution, clicking Expand will substitute the address with the addresses found in the corresponding alias/distribution. If no item is selected in the list box, Expand will perform a similar operation on all addresses in the list box which are aliases/distributions. Note, Expand only expands alias/distribution which are defined in the current alias file being edited. For example if an alias contains the alias "john", "john" will only be expanded if it is defined in the current file.
    5. Contract: This is nearly the opposite of Expand. Like Expand, it will operate only on one address if it is selected, otherwise it will operate on all addresses in the list box. However, Contract is careful about what it contracts. In particular, it operates on an address if and only if:
      • the email address is explicitly defined in another alias/distribution in the current file and
      • this other alias/distribution in which the email address is defined has, at most, three addresses in its definition.
      This is a bit terse, but for a good reason. To demonstrate why, consider the following alias file:
      ProjectList: jordan1@home.ca, jordan2@work.ca, tracy@foo.bar
      Jordan: jordan1@home.ca, jordan2@work.ca, jordan3@laptop.com
      DistroList: tracy@foo.bar, hans@down.de, einstein@hair.com, \
      fred@rick.com, apple@day.ca, ... , person100@years.old
      Now, suppose the ProjectList alias was selected and the Contract button pressed. If there were not a three-address limit, the alias would then read
      ProjectList: Jordan, DistroList
      and so all of DistroList is included in ProjectList and not just tracy@foo.bar. This may not be desirable. With the three-address limit, the line would become
      ProjectList: Jordan, tracy@foo.bar
      (note, that Jordan contains one more email address than what was in the original ProjectList. This might be ok if all the addresses in Jordan belongs to the same person). Really, Contract is meant to replace several email addresses in an alias/distribution which belong to one person only and replace these addresses with an alias or distribution name for brevity. So use with caution.

      If the number 3 is unsatisfactory (i.e., you want the limit to be 2 addresses or 8, etc.), change the line $UpperLimit=3;.


Issues

The following lists a few issues with mafe

  1. When saving an alias file, mafe first saves the distributions in alphabetical order and then the aliases in alphabetical order. It just looks nice to read. However, it does potentially pose a problem since an alias may then be defined before it is used (since in nmh an alias needs to be referenced before it is defined). If this is the case, repeat the alias file name in .mh_profile:
    AliasFile: .mh_aliases1 .mh_aliases2 .mh_aliases1 .mh_aliases2

  2. mafe was written in Perl with the Tk module. It would have been nice to have written it in Tcl+Tk, so that it would be more native to the exmh package. Perhaps one day I'll sit down and learn Tcl and do this. Anyone up for the challenge of porting is more than welcome.

Andrew Billyard (
andrew_billyard@alumni.REMOVETHISBIT.uwaterloo.ca) exmh-2.9.0/misc/mafe/README0000644000170700017070000000023413201227060014530 0ustar valdisvaldisTo use mafe: - extract mafe.tar.gz - copy the perl file mafe to a directory which is in the $PATH environment - to hook mafe into exmh, read help/mafe.html exmh-2.9.0/misc/ns-exmh.tar.gz0000644000170700017070000000577213201227060015462 0ustar valdisvaldis‹àá19ns-exmh.taríýSãÆî~ÿ ] %áåÃùd ÎÐÀ¦„Þ˜»yeŒ½‰Ýsv=»6^éßþ¤µœ¯ãz¼×Öú!±wµ’VÒJÚ]sUe·c·þêÚæV§¯ Ûîš-üh¶¶ô&@·Ó6ÍÖV³Ûh4ºÍæ+è<§P)D*´$À+ß±†CÎä*<5 Uø½,ðÄþôS³Ÿ‡GÃ4»íöJûoµÛ[©ýÍn³ƒöo™­Ö+0ŸGœYø‡Û¿¾ù$`@ì@†}áxC90”b '½ Ê>æk6 …„H1˜x¡ ïû‡8fÏq töù¾˜x|¡€;Iø£^ã,T¶°z ÙIÆm¦j¿*z>ÛÆÁHL^Q_©8¶<¿†ïW–Òs±¡ŒXyg+Á¸r|Â*Ö£úØòÇLÆ+A‰"2 '‚;éÜß}·'‰(Ø>Gܳ­Ð\á« „Ô/°|ô’!×æÔŒ§QsÝ0Œ5Û~ä0ø· OÔÜï3M(¶Î¶1)ù,Z1èõ~Í-"9‡ =δ%ÎßBñ§¢ÎƒâLOïçþ´ç>×{rðnöž°‰Ê}vpÚ'õ*Y÷…mùõk×oC&Ç4ÎNOPBÉ‘ŒQG×Ú$ŸùxeqçŠÝ2êÊz6x<4f:K¶kÉM°äèæâ²l|2 ÞJúvwáäüø~ÿ=î7/§Me@Ì‚da$9T;FáÞ0 }Ôvq8±(•,ÛBï­6¶ñqfDÜaêvÍ”ä¹)%¬*šg™8V ¥B!@ã™â”wt#»õÂ’¶ZÜp?¨)+òÃíB†«©Å¼ŸjÉ–Ì ÙU8®hmPÓ;é…Léµ5fJY#×¹£åeAÈÆ^E L؇ÀR1:µsk¬© 6­Ý¬âµš9މò‰ƒV}üJT` ŸJ¤nšÖ›£ãƒMÍ×Y¬/øí·±„ø_*iávQýã%êÆ•:)–Ëð:¶[j’á„æY¢PÞoL µ,e| %NDwáÔJÚ¾P¬”¾“µ­›ŒVOÙד}Œ=ßcèqØÚÃUŽ1nâ2®ÕubÝx#+ÄØæ)ð­ÈviÕ#â¾à!p†È¨FõÎïB—BBR+”èOY+˜\z‘géFxŽVêƒñd<矕RðŒ|ä]_/Ù2NŸ—íg´áÐÿ0>.SÞГ* Ç0Œ¸Ma”Ôhk´/”•°Þà3Å£ Òúˆ^I^ˆ HFœ²"?¤O+(žÓœ„z:›ÓØÝ¨ÀlCsêÛ°ÇtÑOÄwÐ;=z{–„ÒŠöÐûÏš T:dÕ#\®©¯2 å±éç‰Þfâü~6æÍFÆ Å6øÿH¶RÌgvÈœ ëâ€qޱ«ˆa‡Gh6Öu‘*×ÂÿÌý;ØÅF6Ttý+ŽÞÀ 8°AKÑv˜³cóŸ1ßWzF4Stì 0‚q6GZé-ÁX}Ξ•8v!¡ôIÈQú˜HRÁ•éC8Kûm;}º¶íŒP(M‚Õ’8›ÊvÇQøÛΌߴ–9eÚØu¦T¨o &ì†ÉÄÈ8]Šâš-)Îg¡^MÊ–^‚A“´¢ck)`LSÓ€º›ÔÅ<¨ „¢LQ3Èu˜RÃÁgèߨœ*-®˜¯ØJLÄ+§á>Qõr²ƒ¸sJ;Eþƒé˜”Ë"J5ü…TuRИq6Huêü.&àZ7¨`ôtüÓÎVƒ·"1jµãºóB­hmÔ5ÕîΗ®ý+&ä²?ˆÛù•V$7f|Ä$Ƶ¸]½¨N#¯T0 å) –YÚ¹›†‚ ¯‡(ðôáL³‰W`““ ëaµo]K ö=eG:,©ÕsÛXÈœíû³sÉ2Y×b‘~da©!ñA(c:˜ß /.z”nÅGLÊ‘ïÀu†pµAà[6C»/3IiãªhÍ‚PÅc ónÐVŬÒp(ÐO#åRýÎ ºÈm¥°„JžÄd1£ÓCôŸQß¹ôçMŒñY-æmΘ(Õ¦÷LÞˆ ™ª‘ô©VŽÐ‡6Ã')4óKœ—¶'s!5»X‘Ê£ëô½M6HÏÒmßsðh˜Ÿ?ÿkw€}[[­VǤó¿þçç?/k¯çöÝO¹†¡°– ¿¸ ¬Ð…Y”‡N|ÑÆd¬s0;N †›Ê?qÒ(-¿i7fÉRSˆó铹%1¸\L<>TÓ0¨KXŸ2¸ÜÝ­6î±.!W¡U™ô‘dõ4øê»©óÈ÷á[2ò—çàñÈýo£Óè¦ù¿c6›ºþowóüÿ°ö$€i?u }öœ\®¦¿×FÒ+ƒÏ9F=ÚÛǼo…:â]3_LjÆ dœíþxp6Àý=$7ºÈûàdÎðîèìö`p¼78|m ÎöŽ÷Nw3Õï]×Óå…ÍhG·ÆZ¯‡DG¶m¬õý€¯ë¥ãý2T„ªíØFŒ«¾ãëá[ÒS_3ôðmõü½¡ÇÙ˜öüë?PÝw”dƵ‘îèñ{Gï¡]kâÜdªé8uƒ‰³zÝßœà¿»ÝÆ_.Ð8ò.–¦ ×0,ßßFv‰vËíµr·c- £°^Jè£@"Õ}Ú£§Ø6a÷zˆˆSÛ8µÙýP\/=¥ü¡8ý¼Àãtsío…ñGÇ“P `Õ(TÇ7˜Cg[ÓKýå­`º Þmf&7GÙ°}fqäŒÎªLñ6kS¹dÁœ—:xúEÀsðx4þ7ÛÉ÷?ÍvÓìêøßíäñÿ%àɾÿIÈ0àˆvYC:…¦\@Gº˜˜äV°”˜Ä"¼InzUz†ØÓm§Šl›)U¡o%ðuˆ£"Éjÿ—_ä¬yCî°!\]Å:¸r§¶dš0ò‘h ºä“‚øÐ}'‹´ú¦}íO_^ÏŒ^~-<‹ò•ªúS½·š½Z}ôVu†ûÂeÕbïâõÏ'&ºâ>fkÕeÈ ÏU;è ¸Qò†©,ÆÿÓƒ½ýþÁóðx$þCWŸÿwLÓl`?ÿ5;íüüïEàLÐÅá¶a4Êpàxñi-oz® s jÄGâúÅ5`[<Ô‘•>ƸŽ<ŒÝqK2°h–ØIå½QPwŠîré¦× 1x¨©*t°D߯0Çh–±ŸÙ5/:„ÔÇdŠn4“ÊÌh•õwQÜ“‚E£]^òù(Ǩ/øˆÔ(”Ò£+!]¦&Ç–Xô}Ñ×¥~\ºtS‘ýÒ´S†> ŠC£ïdõÁ %R¢øú©ƒËìù?Eµ'fðêñû?èèïÿÍfËlw·ôý_·µ•¯ÿ—€äüŸNþéÜŸÙ®€âz£Hgêá8¨Ó >f·¿TNË!‡rÈ!‡rÈ!‡rÈ!‡rÈ!‡rÈ!‡rÈ!‡rø'ÂR£îPexmh-2.9.0/misc/lockedrcvstore0000755000170700017070000000020013201227060015710 0ustar valdisvaldis#!/bin/bash PATH=/usr/lib/nmh:$PATH export PATH lockfile $HOME/Mail/$1/.lock echo $@ rcvstore +"$@" rm -f $HOME/Mail/$1/.lock exmh-2.9.0/misc/archiveoldmail0000755000170700017070000000326213201227060015655 0ustar valdisvaldis#!/usr/bin/perl -w $MHPATH = "/usr/local/nmh/bin"; $MHLIB = "/usr/local/nmh/lib"; open(FOLDERS, "$MHPATH/folder -recurse -all -fast|") or die "Couldn't read folders: $!"; while () { next if (/\/old/); print; chomp; $folder = $_; open(OLDMSGS, "$MHPATH/pick '+$folder' -before -60|") or die "Couldn't pick messages from $folder: $!"; @msgids = grep !/^0$/, ; close(OLDMSGS); chomp @msgids; if (@msgids) { foreach $msgid (@msgids) { open(MSG, "$MHPATH/show '+$folder' $msgid -nocheckmime -noheader -showproc cat|") or die "Couldn't show $msgid in $folder: $!"; while () { chomp; last if (/^$/); if (/^Date:(.*)$/i) { $date = $1; last; } } close(MSG); $subdir = `$MHLIB/dp '$date' -format '%(putnum(year{text}))/%(putstr(month{text}))'`; chomp($subdir); print "refile $msgid -src +$folder -nolink +$folder/old/$subdir\n"; system "$MHPATH/refile $msgid -src '+$folder' -nolink '+$folder/old/$subdir'"; } $exmhdisplayfile = "$ENV{'HOME'}/.exmh/.display"; if (-f $exmhdisplayfile) { $exmhdisplay = `cat $exmhdisplayfile`; chomp $exmhdisplay; if ($exmhdisplay) { print "Telling exmh\n"; open(WISH, "|wish -f -display $exmhdisplay") or die "Couldn't open wish on $exmhdisplay: $!"; print WISH < script that comes with ExMH (typical location: C). =item -no-write Do not rewrite the messages; instead, output a line for each message noting the actions that would be taken. =item -debug Output debugging info to stderr. =back Note that options will also be read from the C entry in your C<.mh_profile> file, in traditional MH style. =head1 INSTALLATION FOR SCAN To display the results in scan(1) output, use something like the following for the subject-display part of the scan.form file: %(decode{x-mh-thread-markup})%(decode{subject}) If you do not have a "scan.form" file of your own, you will need to set it up. This functionality is accessed using the -form or -format switches to the scan(1) command. To use this, copy the /etc/nmh/scan.default file to your ~/Mail dir and modify it with the above line, then add scan: -form scan.form to your ~/.mh_profile. =head1 INSTALLATION FOR EXMH Add the following function to your C<~/.tk/exmh/user.tcl> file: proc Folder_Thread {} { global exmh Background_Wait Exmh_Status "Threading folder..." blue if {[Ftoc_Changes "Thread"] == 0} then { if {[catch {MhExec mhthread +$exmh(folder)} err]} { Exmh_Status $err error } else { # finish off by using the ExMH packing logic to redisplay folder Folder_Pack # then show the first unseen message Msg_ShowUnseen } } } Next, you need to rebuild the C file. Run C and type: auto_mkindex ~/.tk/exmh *.tcl Now add a button to run this function. To do this, you must exit ExMH first, then edit the C<~/.exmh/exmh-defaults> file and add these files at the top of the file: *Fops.ubuttonlist: thread *Fops.thread.text: Thread *Fops.thread.command: Folder_Thread Restart ExMH, and there should be a new button marked B on the folder button-bar. Press this to re-thread the current folder. =head1 NOTES The threading algorithm uses the In-Reply-To, Message-Id and References headers. Thanks to JWZ for guidance, in the form of his page on threading at C. The 'X-MH-Thread-Markup' headers are encoded using RFC-2047 encoding, using 'no-break space' characters for whitespace, as otherwise MH's scan(1) format code will strip them. Here's an example of the results: X-MH-Thread-Markup: =?US-ASCII?Q?=a0=a0=a0=a0=5c=2d=a0?= =head1 TODO dealing with private sequences (stored in .mh_profile); limiting displayed thread-depth to keep UI readable (so far has not been a problem). =head1 BUGS duplicate messages will always be shuffled in order each time C is run, due to handling of identical Message-Ids. =head1 DOWNLOAD Latest version can be found at http://jmason.org/software/mhthread/ . =head1 AUTHOR Justin Mason, C =head1 VERSION version = 1.5, Apr 25 2003 jm =cut sub usage { die " usage: mhthread [options] +folder mhthread [options] /path/to/folder options accepted: [-debug] [-no-write] [-fast] [-lock] "; } use vars qw( $mh_sequences_file_name $mhthread_options ); read_mh_profile_data (); if (defined $mhthread_options) { unshift (@ARGV, split(' ', $mhthread_options)); } my $folder = ''; my $no_write = 0; my $fast = 0; my $lock = 0; my $dbg = 0; use Getopt::Long qw(:config no_ignore_case prefix_pattern=(--|-)); GetOptions( "debug" => \$dbg, "fast" => \$fast, "lock" => \$lock, "no-write" => \$no_write, '<>' => sub { $folder = $_[0]; } ); usage unless ($folder =~ /\S/); ########################################################################### use vars qw( %TZ %MONTH $locked_folder_lockfile ); use strict; use Time::Local; if (!-d $folder) { chomp ($folder = `mhpath $folder`); if (!-d $folder) { usage(); } } init_tz(); if ($lock) { $SIG{INT} = $SIG{TERM} = \&unlock_and_die; mh_lock_folder ($folder); } # trap die()s eval { my $ctx = thread_folder ($folder); mh_rewrite_folder ($folder, $ctx); }; my $err = $@; # always unlock, even if we died if ($lock) { mh_unlock_folder ($folder); } # and finally, propagate the death exception if ($err) { die $err; } # otherwise we're fine, exit 0 exit; ########################################################################### sub mh_lock_folder { $locked_folder_lockfile = $folder."/.lock"; system ("lockfile", $locked_folder_lockfile); if ($? >> 8 != 0) { die "failed to lock folder $folder (lockfile $locked_folder_lockfile)\n"; # $locked_folder_lockfile = undef; # not needed, we're dead ;) } } sub mh_unlock_folder { if (defined $locked_folder_lockfile) { unlink $locked_folder_lockfile; $locked_folder_lockfile = undef; } } sub unlock_and_die { mh_unlock_folder(); die "killed by signal\n"; } ########################################################################### use vars qw(@to_unlink @to_rename %num2seq %newseqs); sub mh_rewrite_folder { my ($folder, $ctx) = @_; my $newnum = 0; my %msg_rewritten = (); foreach my $num (@{$ctx->{all_message_locs}}) { $msg_rewritten{$num} = 0; } # read the mh_sequences file, and create the map of sequences in this # folder... cf. man mh-sequence, man mark. %num2seq = (); %newseqs = (); if (open (IN, "<".$folder."/".$mh_sequences_file_name)) { while () { /^([^:]+): (.+)$/ or next; my $seq = $1; my $msgs = $2; $newseqs{$seq} ||= []; foreach my $spec (split (' ', $msgs)) { if ($spec =~ /(\d*)\-(\d*)/) { my $start = $1; $start ||= 1; my $end = $2; if (!$end) { # not supposed to happen with nmh at least warn "oops! no end for sequence: '$_'"; $end = 9999; } my $i; for ($i = $start; $i <= $end; $i++) { $num2seq{$i} ||= []; push (@{$num2seq{$i}}, $seq); } } else { $num2seq{$spec} ||= []; push (@{$num2seq{$spec}}, $seq); } } } close IN; } my $changed = 0; foreach my $line (@{$ctx->{sorted}}) { $newnum++; my $oldnum = $line->{num}; my $oldprefix = $line->{existing_prefix} || ''; my $newprefix = $line->{prefix} || ''; $msg_rewritten{$oldnum} = 1; if (mh_rewrite_reorder_message ($ctx, $folder, $oldnum, $newnum, $oldprefix, $newprefix)) { $changed = 1; } } if ($changed) { # now if we missed any messages we read to start with, something's wrong # in the algorithm, and we could lose mail. Don't modify anything; just # die instead. my $failures = 0; foreach my $num (@{$ctx->{all_message_locs}}) { if (!$msg_rewritten{$num}) { warn "mhthread: message not threaded, adding to end: $num\n"; $newnum++; if (!mh_rewrite_reorder_message ($ctx, $folder, $num, $newnum, '', '')) { $failures++; warn "mhthread: oops! failed to recover: $num\n"; } } } if ($failures) { die "mhthread: not modifying old messages due to errors.\n"; } # otherwise, go right ahead and unlink/rename... foreach my $name (@to_unlink) { unlink $name or warn "unlink $name failed: $!"; } foreach my $name (@to_rename) { rename $name.".new", $name or warn "rename $name.new -> $name failed: $@"; } # now mark the sequences with the new message numbering foreach my $seq (keys %newseqs) { my @messages = @{$newseqs{$seq}}; next unless (scalar @messages > 0); my @cmd = ('mark', '+'.$folder, @messages, '-sequence', $seq, '-add', '-zero'); system @cmd; if ($? >> 8 != 0) { warn "'".join (' ',@cmd)."' failed\n"; } } } } sub mh_rewrite_reorder_message { my ($ctx, $folder, $oldnum, $newnum, $oldprefix, $newprefix) = @_; my $oldname = $folder."/".$oldnum; my $newname = $folder."/".$newnum; if ($oldnum eq $newnum && $oldprefix eq $newprefix) { if ($no_write) { print "no move for $oldnum; subj-pfx '$newprefix'\n"; } $dbg and warn "debug: $oldnum: no differences, skipping move/rewrite"; return 0; } if ($no_write) { print "mv $oldnum $newnum; subj-pfx '$newprefix'\n"; return 0; } $dbg and warn "debug: $oldnum->$newnum: move/rewrite"; if (!open (IN, "<".$oldname)) { warn "cannot read $oldname: $@"; return 0; } concat(OUT, ">".$newname.".new") or die "write to $newname.new failed: $@"; while () { # remove an old thread-subject /^X-MH-Thread-Markup: / and next; /^$/ and last; # end of headers print OUT; } print OUT "X-MH-Thread-Markup: ".$newprefix."\n\n"; # dump the body # TODO: use read()/syswrite() while () { print OUT; } close IN; close OUT or die "write to $newname.new failed: $@"; push (@to_unlink, $oldname); push (@to_rename, $newname); foreach my $seq (@{$num2seq{$oldnum}}) { push (@{$newseqs{$seq}}, $newnum); } return 1; } ########################################################################### # note: these global vars are ONLY used inside thread_folder (and # inside functions called by that fn). They are undef'd at the end # of that function's scope. # use vars qw(%mid2msg %tree %toplevel %subjtop %subjsets %subjearliest $uniqid ); sub thread_folder { local ($_); %mid2msg = ( ); # message-id to msg object %tree = ( ); # the threaded tree %toplevel = ( ); # top-level nodes of the tree %subjtop = ( ); # top-level nodes for a given subject string %subjsets = ( ); # top-level nodes with the same subject %subjearliest = ( ); # date of earliest message with that subject $uniqid = 1; # used to "unique-ify" duplicate message-Ids # %dupmessages = (); my $ctx = { sorted => [ ], all_message_locs => [ ], done => { } }; if ($fast) { eval { use Storable; $ctx->{fcache} = retrieve ($folder."/.thread.tmp"); }; if ($@) { $ctx->{fcache} = { }; } # kill it if it's corrupt } opendir(DIR, $folder) or warn "cannot opendir $folder: $!\n"; my $num; while (defined ($num = readdir(DIR))) { next unless ($num =~ /^(\d+)$/); my $msgpath = $folder."/".$num; my $stat_details; my $cachedmsg; if (defined $ctx->{fcache}) { my @st = stat($msgpath); if (!defined $st[7]) { warn "cannot stat, skipped: $msgpath\n"; next; } $stat_details = join('|', @st[0 .. 5], $st[7], $st[9], $st[10]); $cachedmsg = $ctx->{fcache}->{$num}; my $cstat = (defined($cachedmsg) ? $cachedmsg->{stat_details} : ''); if ($cstat eq $stat_details) { $dbg and warn "debug: $num cached message matches"; } else { $dbg and warn "debug: $num cached message no match ". "($stat_details vs $cstat)"; undef $cachedmsg; } } my $msg; if (defined ($cachedmsg)) { $msg = $cachedmsg; } else { my $hdrs = mh_read_message_headers ($ctx, $num, $msgpath); next unless defined($hdrs); $msg = parse_message_headers ($ctx, $num, $hdrs, $stat_details); } my ($subj, $sortsubj, $intdate, $irt, $re_in_subj, $mid); $subj = $msg->{subj}; $sortsubj = $msg->{sortsubj}; $intdate = $msg->{intdate}; $irt = $msg->{irt}; $re_in_subj = $msg->{re_in_subj}; $mid = $msg->{mid}; push (@{$ctx->{all_message_locs}}, $num); $mid2msg{$mid} = $msg; # create the node for that mid, if not already existing if (!exists $tree{$mid}) { $tree{$mid} = { }; } if (!defined $irt) { $dbg and warn "debug: $msg->{num} no IRT ($msg->{mid} $msg->{intdate})"; add_to_top_level ($msg); } else { my %seen = (); { next if ($seen{$irt}); $seen{$irt} = 1; if (!exists $tree{$irt}) { $tree{$irt} = { }; } $dbg and warn "debug: $msg->{num} IRT $irt ($mid $msg->{intdate})"; $tree{$irt}->{$mid} = $msg; } } } closedir DIR; # store it here. we don't care if we rewrite the order later on, # we just want to cache the least-changing messages in the folder. # Doing caching post-writes will require more logic in the threading # part to update this cache, and let's not bother with that! if ($fast && !$no_write) { eval { use Storable; store ($ctx->{fcache}, $folder."/.thread.tmp"); }; if ($@) { warn "failed to cache folder data: $@"; } } # now find "orphaned" message trees, and put them into the top level foreach my $mid (keys %tree) { next if (defined $mid2msg{$mid}); # it has a parent # OK, this is a message-id used in an In-Reply-To header, but we # don't have the msg. Reparent all its children down to the top-level # instead. foreach my $kid (keys %{$tree{$mid}}) { my $msg = $mid2msg{$kid}; # if it's already in the top-level, ignore it next if (defined $toplevel{$msg->{mid}}); if (!defined $msg) { warn "oops! nonexistent kid for $mid"; } $dbg and warn "debug: $msg->{num} orphaned ($msg->{mid})"; add_to_top_level ($msg); } } sub add_to_top_level { my ($msg) = @_; my $sortsubj = $msg->{sortsubj}; my $intdate = $msg->{intdate}; $toplevel{$msg->{mid}} = $msg; # if there was no re: tag, add it to the 'top' set for that subject line if (!$msg->{re_in_subj}) { $subjtop{$sortsubj} = $msg; } $subjsets{$sortsubj} ||= [ ]; push (@{$subjsets{$sortsubj}}, $msg); if (!exists ($subjearliest{$sortsubj}) || $subjearliest{$sortsubj} > $intdate) { $subjearliest{$sortsubj} = $intdate; } } # ok; try to figure out a rudimentary tree from the Subject line alone, # for messages that did not use 'In-Reply-To'. foreach my $subj (keys %subjsets) { # is there a suitable candidate for a 'parent' message? my $parent = $subjtop{$subj}; if (!defined $parent) { next; } foreach my $msg (@{$subjsets{$subj}}) { if ($msg->{re_in_subj} != 0) { # this msg has "Re:", but has no In-Reply-To. reparent it $tree{$parent->{mid}}->{$msg->{mid}} = $msg; delete $toplevel{$msg->{mid}}; } } } # now recursively display the tree. Sort by the date of the earliest message # with that subject line, and by existing number if there's a dup. foreach my $top (sort { $subjearliest{$toplevel{$a}->{sortsubj}} <=> $subjearliest{$toplevel{$b}->{sortsubj}} or $toplevel{$a}->{intdate} <=> $toplevel{$b}->{intdate} or $toplevel{$b}->{num} cmp $toplevel{$a}->{num} } keys %toplevel) { dig_thru_tree ($ctx, 0, $top, $toplevel{$top}); } foreach my $mid (keys %mid2msg) { if (!$ctx->{done}->{$mid}) { my $msg = $mid2msg{$mid}; $dbg and warn "debug: $msg->{num} missed ($msg->{mid})"; push (@{$ctx->{sorted}}, { num => $msg->{num}, existing_prefix => $msg->{existing_prefix}, prefix => '', subject => $msg->{subj} }); } } # delete these state arrays, they're unnecessary now undef %mid2msg; undef %tree; undef %toplevel; undef %subjtop; undef %subjsets; undef %subjearliest; return $ctx; } sub dig_thru_tree { my ($ctx, $level, $mid, $msg) = @_; my $num = $msg->{num}; my $subj = $msg->{subj}; # OK, we want a result like this: # X-MH-Thread-Markup: =?US-ASCII?Q?=a0=a0=a0=a0=5c=2d=a0?= # just use the encoded string directly, it's quicker and simpler. my $MARKUP_START = '=?US-ASCII?Q?'; my $MARKUP_NODE_LAST_CHILD = '=5c=2d=a0'; # "\- " my $MARKUP_NODE_CHILD_W_SIBLINGS = '=7c=2d=a0'; # "|- " my $MARKUP_TREE_EMPTY = '=a0=a0'; # " " my $MARKUP_TREE_BRANCH = '=7c=a0'; # "| " my $MARKUP_END = '?='; # TODO: limit levels to 3 for UI reasons my $levelstr = $MARKUP_END; my $iterlev = $level; my $itermsg = $msg; while ($iterlev > 0) { if ($iterlev == $level) { if (!defined $itermsg || $itermsg->{last_in_level}) { $levelstr = $MARKUP_NODE_LAST_CHILD.$levelstr; } else { $levelstr = $MARKUP_NODE_CHILD_W_SIBLINGS.$levelstr; } } else { if (!defined $itermsg || $itermsg->{last_in_level}) { $levelstr = $MARKUP_TREE_EMPTY.$levelstr; } else { $levelstr = $MARKUP_TREE_BRANCH.$levelstr; } } # get the msg object for the parent message my $irt = $itermsg->{irt}; if (defined $irt) { $itermsg = $mid2msg{$irt}; } $iterlev--; } $levelstr = $MARKUP_START.$levelstr; # printf ("%4d %s%s\n", $num, $levelstr, $subj); push (@{$ctx->{sorted}}, { num => $num, prefix => $levelstr, existing_prefix => $msg->{existing_prefix}, subject => $levelstr.$subj }); $ctx->{done}->{$mid} = 1; # within the tree, just sort by post date (or by number if there's # a duplicate). my $kids = $tree{$mid}; my @sorted = (sort { $kids->{$b}->{intdate} <=> $kids->{$a}->{intdate} or $kids->{$b}->{num} cmp $kids->{$a}->{num} } keys %{$kids}); if (scalar @sorted > 0) { # mark the last one in this level, so it can be displayed with "\-", # instead of "|-" $kids->{$sorted[$#sorted]}->{last_in_level} = 1; # and recurse foreach my $kid (@sorted) { dig_thru_tree ($ctx, $level+1, $kid, $kids->{$kid}); } } } ########################################################################### sub mh_read_message_headers { my ($ctx, $num, $msgpath) = @_; if (!open (IN, "<".$msgpath)) { warn "cannot open, skipped: $msgpath\n"; return undef; } my $hdrs = "\n"; while () { $hdrs .= $_; /^$/ and last; } close IN; return $hdrs; } ########################################################################### sub parse_message_headers { my ($ctx, $num, $hdrs, $stat_details) = @_; my $mid = ''; my $subj = ''; # these are not stored in the public "msg" object after parsing my $date = ''; my $pfx = ''; # remove newlines from headers; makes them easier to parse $hdrs =~ s/\n[ \t]+/ /gs; $hdrs =~ /\nMessage-I[dD]: <([^\n]+)>/ and $mid = $1; $hdrs =~ /\nSubject: ([^\n]+)/ and $subj = $1; $hdrs =~ /\nDate: ([^\n]+)/ and $date = $1; $hdrs =~ /\nX-MH-Thread-Markup: ([^\n]+)\n/ and $pfx = $1; my $intdate = parse_rfc822_date ($date); $intdate ||= 0; # ensure the message-id is unique; if it already exists (a dup msg) then add # some extra bits until it's unique. TODO: figure out a workaround to avoid # the ensuing shuffling of messages; with this algo, if messages 4 and 5 are # identical, then they'll always be swapped each time this is run. if (exists $mid2msg{$mid}) { my $origmid = $mid; while (exists $mid2msg{$mid}) { $uniqid++; $mid .= "|".$uniqid; } # $dupmessages{$origmid} ||= [ ]; # push (@{$dupmessages{$origmid}}, { # 'mid' => $mid, # 'num' => $num # }); } # figure out which message this was a child of. Some In-Reply-To hdrs # contain the email addr of the parent's sender, so add all mid-like # ids; no messages will be found with mid == emailaddr, so it doesn't # matter. For the References hdr, just take the last one. my @irtsary = ($hdrs =~ /\nIn-Reply-To: (?:[^<\n]*<([^\n>]+)>)+/); my @refs = ($hdrs =~ /\nReferences: (?:[^<\n]*<([^\n>]+)>)+/); if (scalar @refs != 0) { unshift (@irtsary, pop @refs); @refs = (); } # In-Reply-To = last of ( reference1, reference2, in-rep-to1, in-rep-to2 ) my $irt = pop @irtsary; # now clean up the subject for sorting, and determine if we have a "Re:" tag my $sortsubj = $subj; my $re_in_subj = 0; while (1) { my $was = $sortsubj; $sortsubj =~ s/^re\[\d+\][:;]\s*//ig and $re_in_subj = 1; $sortsubj =~ s/^re[:;]\s*//ig and $re_in_subj = 1; $sortsubj =~ s/^\s*//ig; ($was eq $sortsubj) and last; } my $msg = { num => $num, subj => $subj, sortsubj => $sortsubj, intdate => $intdate, irt => $irt, re_in_subj => $re_in_subj, existing_prefix => $pfx, mid => $mid }; # cache if we're in "fast" mode if (defined $ctx->{fcache}) { $msg->{stat_details} = $stat_details; $ctx->{fcache}->{$num} = $msg; } return $msg; } ########################################################################### # Parse RFC-822-format dates. sub init_tz { # timezone mappings: in case of conflicts, use RFC 2822, then most # common and least conflicting mapping %TZ = ( # standard 'UT' => '+0000', 'UTC' => '+0000', # US and Canada 'AST' => '-0400', 'ADT' => '-0300', 'EST' => '-0500', 'EDT' => '-0400', 'CST' => '-0600', 'CDT' => '-0500', 'MST' => '-0700', 'MDT' => '-0600', 'PST' => '-0800', 'PDT' => '-0700', 'HST' => '-1000', 'AKST' => '-0900', 'AKDT' => '-0800', # European 'GMT' => '+0000', 'BST' => '+0100', 'IST' => '+0100', 'WET' => '+0000', 'WEST' => '+0100', 'CET' => '+0100', 'CEST' => '+0200', 'EET' => '+0200', 'EEST' => '+0300', 'MSK' => '+0300', 'MSD' => '+0400', # Australian 'AEST' => '+1000', 'AEDT' => '+1100', 'ACST' => '+0930', 'ACDT' => '+1030', 'AWST' => '+0800', ); # month mappings %MONTH = (jan => 1, feb => 2, mar => 3, apr => 4, may => 5, jun => 6, jul => 7, aug => 8, sep => 9, oct => 10, nov => 11, dec => 12); } sub parse_rfc822_date { my ($date) = @_; local ($_); my ($yyyy, $mmm, $dd, $hh, $mm, $ss, $mon, $tzoff); # make it a bit easier to match $_ = " $date "; s/, */ /gs; s/\s+/ /gs; # now match it in parts. Date part first: if (s/ (\d+) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) / /i) { $dd = $1; $mon = lc($2); $yyyy = $3; } elsif (s/ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) +(\d+) \d+:\d+:\d+ (\d{4}) / /i) { $dd = $2; $mon = lc($1); $yyyy = $3; } elsif (s/ (\d+) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{2,3}) / /i) { $dd = $1; $mon = lc($2); $yyyy = $3; } else { return undef; } # handle two and three digit dates as specified by RFC 2822 if (defined $yyyy) { if (length($yyyy) == 2 && $yyyy < 50) { $yyyy += 2000; } elsif (length($yyyy) != 4) { # three digit years and two digit years with values between 50 and 99 $yyyy += 1900; } } # hh:mm:ss if (s/ (\d?\d):(\d\d)(:(\d\d))? / /) { $hh = $1; $mm = $2; $ss = $4 || 0; } # numeric timezones if (s/ ([-+]\d{4}) / /) { $tzoff = $1; } # UT, GMT, and North American timezones elsif (s/\b([A-Z]{2,4})\b/ / && exists $TZ{$1}) { $tzoff = $TZ{$1}; } # all other timezones are considered equivalent to "-0000" $tzoff ||= '-0000'; # months if (exists $MONTH{$mon}) { $mmm = $MONTH{$mon}; } $hh ||= 0; $mm ||= 0; $ss ||= 0; $dd ||= 0; $mmm ||= 0; $yyyy ||= 0; my $time; eval { # could croak $time = timegm ($ss, $mm, $hh, $dd, $mmm-1, $yyyy); }; if ($@) { return undef; } if ($tzoff =~ /([-+])(\d\d)(\d\d)$/) # convert to seconds difference { $tzoff = (($2 * 60) + $3) * 60; if ($1 eq '-') { $time += $tzoff; } else { $time -= $tzoff; } } return $time; } sub read_mh_profile_data { my $mhprof = $ENV{HOME}."/.mh_profile"; if (defined $ENV{MH}) { $mhprof = $ENV{MH}; } $mh_sequences_file_name = '.mh_sequences'; $mhthread_options = undef; if (open (IN, "<".$mhprof)) { while () { if (/^mh-sequences: (.+)$/) { $mh_sequences_file_name = $1; next; } if (/^mhthread: (.+)$/) { $mhthread_options = $1; next; } } close IN; } } exmh-2.9.0/misc/netscape-remote.tar.Z0000644000170700017070000012351613201227060016764 0ustar valdisvaldisnÊЙ3& œ2-ä”ió†N™"JœH±¢Å‹3jÜX 0nÔ¨ÀcÈ6b”4ƒ•&cz,iƒF4PÚ€¡ÒcK<äH´¨Ñ£H+Ö™C'Œœ•kʸA“ãÒ2O«Z”9Óg 5µŠK¶¬Ù³<˜paÇC¬Lx¶.Y E’4yeO–.aríZófN;e¬licÉ¡v#K¾¸´éSQ§Ö½šÕìàÅ_ÃNMºôè´ "TÈÐዸs¥¼ihº¶Džk¾äëWpË݃aÌèÙ¸È7bÜXl|gIÛÐÇVv U*Õ³œë~ö öeôïàÃxÆÌœcÚ˜yGÎ5eÆÐAogŽû† ÄëßÏ¿¿ÿÿ(`D¨­µš[®Áö‚eÀñÆiÐñ†y hnÝwRJ¾ 5çØq9)·˜ ÉÙðœ…âMw ™]gVvgmÇShÞ±¨£€ä™‡žz칟|ôÙ7Û|ªÖVkeä·ã“PF)å”T†—$[¬½õš\/ár¤QÆU^„¡n0õÅaL¿ “qÄÙ„“N0(æSJˆ­Xæd.V§vs`¥W u·ç¡£½Æ†˜_^‘†.ŒñB .Äðu”‚u¸‚ 4€ œ5Ì Ã ¡ÆC7¼ð‚¯=ER$qTLê /4ñ†§œ²ñ)¢â@j §Ú ꪭ¾úB¤õ¥q†>D© ½þºiÂÊ@¬ 2è@C:Èò¬º kc°ñFAl¸Ð ºZê+°Üûi¸ã’ª¬ªé:;ƯfH[‡B.<ª+¶˜jì§9€¢<‘1ÀÍÂ*EAÑDºæpi¦ÛvñÄ0±«û•e|‘¥C‘ÖËëeQ23À 1²!‹nƽ†UÁl”‘°ºâp)ul†§1Ôð)²ªZŒ®Ó¯á$¢`#ó’ZB á´Õ†}ÛW¦Ù›M3 nHkò„ç^joÆu˜Yç· 5Êh}'žkœ‘„d”‡ t´«ÀÀn|ÆÁMb®¹ îžq9ÁÒºð7KžyéF“M]ÒM*nûí¸ç®ãØ3?ä¹Á )Ž¡^nçíSÜ,ÉPw *‚U÷ 2à¢zÇ`" ºWÕgàÎhgeÙh½¡Ù—?Ñ!€ð‚ φ ŒÂ™Î1v„ÁFý ˜1!sÈSÒ‚ÈrR¡þœ’†0ˆ!i÷›šÎÆ 08±;Z è‚øÍO*X±`Î@†:H¨ L¼Ø,åQg ¡ ßE0üaBÚ’A¥|æÁ!¼yÓР@ !è’ @ƒ,14xb ž¨,#(DSSxƒèp§hÊoèRø«%>n ©€†4Üïw›S)˜8(Ðý»"µÈE/îtx¬X,ò±‹r£Éèž! v“ ݰ¨6Dh„‘ƒ%í—mIâÉàF0¥A &Ô”AÀRš¡…ê ‰0»²a :P»¾ð:6À¡ºÃ"g[Òá í™]ðЃ,E/p¼<7´0 d %:é†û™Á=m%é⨴Går—½ü¥H€Î2øR A Zp‡¡¡•c{… P ñ)"Ÿ µsMy Ù.q®.ŽŒ òéÇš )A0yéNu²S˜é„§<éiO|®aŸýüg@š‚JˆBM¨J‡58Ts‹èD×PÑϹ/£MgÖÙÎwÆsžõ d ÆÊô`C¦°Ò@%M>âl6ˆ•¬¢r XT@@ðÃmþj-ªGÕ*R¤–”©O}B &A +§Uã£Ài•«rä\¨´‚´£Cý(G:Ò¤ÞS¬Q‘C˜',á®Uu'_Ãú¨È –°e0ìb×zXƺU©l CYç0Y"H•ªÝ+V!ÛU¿~UgbÕTY¹‰Ö "–¨¥…C[IªÔ1ÀÁAvdí …×êU³XõëV“Ød¶ç]cšÃÿl»ÊÜ’ÕŽ¼Õ¨¡.JšÒn4•¿09‚ÄÐÂÝž5 `#{ø^I¢! ‘¤ ç†õ‚À –dîHÝ‚÷¬Kt¬Çè>Iºnjgá'ň•ÜΡƒ¨Ü zà„'8¡—c×ë¾@»¸=ãŒ”Š›$¹ø S!cf‰O¬4<ˆ$61Š©õ –A„À¤µìd™ á€™Ì7Å×=ƒ |ceêXÈ Èò–Ûð…9ÔÁ VÞ1–Ý£e.ƒijsðŸ&¿€àõö`,ÀCžY %íKÀ„C-‡1 ˜–É0Õ¬€HÊA *0ñð…Gµ«‘c-£)½(1l9Lcº²Ø¹–öà$ØC…Yåeöa}:AŸI}hT«6n5^=R˺ӫ®uªWÝå¿ظƒ¬ÇØaïA×¼þ¯Bd@‚ÌÙÐ~@”Ýgiçìt93µ­³í×_¿KàÆ6Ž]ý‚öþú”Î&v¶;-kKï/rêöò«íé2Èú ©å7¾ÅíLû¼@àþVÀ£ü—ocÄWg'8ÏZð…0´@Ah`Ђt¡ñ®:@°ƒˆôñAÿ‚äåpš×^¤cbáå¦6H V¼V'Ô”/`y˜ÖÓáÈ9¨óv‰ÚÁ4UO‘2 h  óà ¾ âÏ|Ô9¿ø¶Òº¥éûëùy¾?þö”ÎêßRã¿ÿi}—{s7´g{G5Ž÷ ¨ ¨i°€üGk(Rùçx¸R ¨~WÇy¿ç~u b 8‚©U‚„‚%¸¥wo×!v‚¿—€&8b85ˆýg‚:b=X8€18bÈ{ h{mÕ:¯Ó´óJˆMÈOÈ„)(…3F… À"e…®…Nx…_Ø…aˆaø…NÈ‚ñä‚>÷„,ÆU˜„WØb78RS(‡c…¤ƒu¨…ñÄ…Khzx…ƒØ……ˆ…8ˆz„+ņ-V„gp„„W@„MðÇÌf‰ô7R™HJÿ׉ŸX‰¡¨@˜hH€{×3(O«(Ys8O¯¨ƒ«H‹•hƒ£¶d}¸…œ¨‹7€³‰’ØV¤D`&×±X@nÔ_ÊxŠ»dG†: Ay–7Xv§y|(:Óšz/ ŒÇ茱(? 2$ Tg’HDBrD- wi 3ÆÂBrýu` f~+v€4& ÔfWy®ƒÑ8œãyÜà8z¦‡zªÇz9ð]à*g {j·tm—W{׈yÔ§:’ràrP’Š%Ä9%ù(ô¨3,IšÂŽœ>`2ðG’!¢òG}0€ƒ—wÂ4“œc +© Á#Ž-ð_ðiŽnw˜'ýõ©–-©}ÐÔRŒG¥•ɸŒf™4Ï8€^I“HyyÙuÛ8BÞè硌i‰±'Oßx.¦åxŽ Ž›ÅŽ ö_ äEÖ ´(öØKùÈ_&Çëåc7’Kù•eà” 'z¤‘©·z­w‘T©‘k÷:¹R’"0’eP’X’*Ù–.©xn“ýÔ5™`7™“; ’xà“1”B™lY”¾ù–Éœž švŽR™šVPèwxqÉMìךÕx¸×Š+…{‘gG“—’$ž I`c0€o§?Y‰`&Ç•{€›`yjqyu'@–|™l- kÿ'oë†êŸÊ«öŸë–…¾8O Ze ª)j ›è ¡cÐ ú‡#µjZ ÐÈj©( ^ö†ei¡^¦ƒ&jeh©¢.ª¡Z0 è‡2Ze,ª¢9*¡í±£úK/*¡5Ú Þ˜l;š£ŒP-ºL‰Už‰ÆŸ-p öRz?ü'¥TzŠòób ]IãtURUÚA+åX_P¥=€ž÷‚G•Nÿ§ü×KqZZ O`I ¤^šò(!&,ÿó] pá`QÇ`ƒ…BQ±tœEvt?i°|âg`¦%?l„G•I`¦xŠ:Xîb©Ÿ%ª@¦Dªâ¨AðU€Æ] O ysP’[@LÆ$©žâiìAB[ÔU™FGÐÚ¬=<Œ”KGµTqÈU=`uUye«b˜™  fvKÖ:Hí:\pú®üºRíá§Æ©Ù~Mr®Ô²TtAýºRªµ˜}•°ºeBp`BýÃUs0\q0‚±Dóäg į + ð¯ÎÇ`Ð…c°0ä,{¬4°v±çêhR¶°ïJ²È'H4ËMd¥t%$!ž#`ïhd"4AãÄ9 @-ÅWUu2醆i®#¥kü´1ì «ýú(ƒðè:—$œÓú× R9ÎG;÷ V›X0€6û¶ÉªXÔÊ-ǤkÍz®: =Pj[W{™ÝÔ\ë^ë`«D¶t¶«›ºÚ·Wë¶p»°[@`6¥v;\ HI€WoËÄ&Ô_÷ʹxµ|»¶Xknp·#Õk(Y¦û¶Õæá„M–ä)«6º&Wº›¬©ë·lû°ÛºÃ…lñqh³Ë¯bV`¡;¼ _«:»¨ ¹Ã‹¼cາx‹¦¶¼ [AdпÂB]ÛF†K“b‹@d¶ ”‰Žkº’;¹üºÖ»ºîãEÚÛÕæ9Êû»ü ¾âKI-T©g –(äµcå¾Óû»ô«ºÚV9ù{¿ AéÖ½þO­v%—4åûµè;¶ëû± ì)ð+¿pÛÀ»º~•¿Ò„nMáý빕Á³lÀ*ö(š2 @½õÛnNÁÂðfÁ2¼°„ªŽâ9œ…­ æ»§¼WM§”¿Ãý: ð:ØÔUhû¾ ü׿GJnpi'»OX¬Å‘X] tJ¥Låŧ[pÐÆÃµpo`Å6«Çõ.uu/̳ |º` qù;qh\ÄýúU ½‚Q…œ¬?üU\h|l³Vɧ]3’4É[ ›,XÿòùÛ¼m0£LZ¿#«ë ®üIZ+¸I£3ªL™c2\ª¬¿gfeSPFð·ËÁ<ÌlûYµ¬?·üÊoÐfád˜¼Ìfc†O[ÖMr¶ÊìXµOpRM¿&¼RrÐ)Ÿ'ËRÐÍßÜdåuË̘DÍÎ+ͻګx«¹ZÏ €?6~!µö—ƒBPuEoKÊ@7„ ¥-]ÐÉÚÐL@=€O0T¿Ë dmÑ“‹Ðÿ³ÑT¬›“]9“¿‰&=@A GP!ݯX*ÍÒ.¬3ÝÒT0Ñ}Ñ `¾A`ÙJ°Ñ:\㘌FÀ1TP²ƒ%²7HJÍÔ«J÷ã ò©–IíOT-–oÀ‚ZíŒ]½Ô³=°ÒG€¬ºiÆ_4ÕM½j½¦c’¿ŽÕý4KsE€ÖjÍÖñ$¦y½×-¬sͦvmOaDxzÍ×Ní° %ËŽMØU}Õ$”ÕÄuOƒÍ×`-Ö-€éëÖ¬å½y«QÝÅŠYÈÃ%ÚöibRÚiP°úÚNÑBª-G¬­Ïÿ(vYv˜§Xé´‘l'¹°9Ö“¹J§E†Æ:¯ññÌ3…^d ÂÝQxPC©¤Å©@>ã¦ò”ÑqÚÏsú á=¢h×àÝŠ-Ñ:ÈÞ˸¬íýIOìMŒoØVU|‰#•ß:Ú÷nÿWÅ^ÆÿÝ¡nƾ? ~àæ=wü¢òÄß:(á˘ßNàý†‹ü‡pCê¡ó$p~i!Î!>ßmý߇fßÞ¾ §ßq5à-.ã{Lã2Þ੨Ç1®Þ:njã>Nã¤tá Gäòýれÿä’¥âHxTãüå.ÞTþQŽã/Hå¥Þ\®ƒ_¾ŒTæðfâ_î䓈½R>Rj^åmŽå§lpnªÉfàSç¸6ç’£çZîsmÞå(ONætž¼A~ç…nh|¨çɦálŽçñÑáŒ.ibŽç„Né§8èhÞV-ÌÜßþéX~nžþÂ>夞nvÎæ©nê£/§óê.²^ê«>O¡^ë²þê£Þç=ꦾãnå­^´‡Îê°ìÇŽëÅËŽêÉ^´’í³>hbÞì`^ìÙžìÓŽìè¶íúîÛžífÞìáÖäùi„÷}TŠüíÎçî«ïS#ïîîëí®ÞЬƒû¾ŒÇïðSæïÀèî&¾ï›~T™ÿ·ð owÊ¥^z¨a*~˽ØLµª}öÄb¿D-ë^vo€°ÓH¡#u°D{Aü‡ò Ûð#O´.Oò·N/ßß(ŠD–ò’Ʀ!Oóm½rP³+?òPô<;ô?eóE!3°MÏô¢kóD/ºR?RÏô8ÿ23õRF×múäò4ÆÎdágügïÖžhö‡ö#d£nOÆn­öoàsÏovO÷Â’÷e<óg¿÷i°÷v¯ö¾¾ö(ΊÎø¾ìâ{÷‰‹‚÷C¾ŒŒoÝ>O—Oé“oÆ:ÈøŸù¡O÷™ÿød<úÏ>RcúŸo⛟âé‰= S; ÿ×j·c¹oòóÔ·ïëªÞT»ŒÃ¿û4Jü8¦ƒÉ¤ü’Ï@zŠT›ðòÔË´ßûò¼ÊÕ¯ Ï\͸ïü×?£3OýräýÛ_` šûåýÀýŶL®ýÐÌÊÌ„üé/ÿÌ_ÿ­Vúâ?;÷ÿËOÿþ¯ùÕ>ügâTYûc&ÒþU33ƒfÜù‹ 0Ç ?øËß\€¿,ü}?81`4s`ý¥¿2S ”ðÛ€%°ÿaÀ8ÿ>à*‹€‹Nî @ ˆfT <36ð!¸ ûƒ0öA©^öf°Ù„Ðf ÆZ38“ÍR”Ö¯þÁ8s`8¹€æo 6A£¥à5£‚š„ )A-X»`ü#ƒšd ~A `\ƒƒ ®2-h«ÙTƒõ® Š™%¨Ç „f_ ’vôþˆ  ƒÛŒ¾A&Xa\„F˜¸#!ÔßO$J¨ 1¡d„š„BOxá (d‚¤Ð~ÁS8ðêà…œÐŽ@AHgL“:æIÝ­¸8€2–˜ E#ÅÊþ# ÿ/4†QƒÞ:å|ø3†‹«x g膨!8EÏìõ¼âµæ:–r†÷êŸÿS¼È!û0‡¾Ž*¾¶¢ 7Œ]:HÆC ´ŒŠWéƒ]óÐĵÃ[¨{r¡ì[qìÛ(»þ)Ø@$‡ÞÆ »™WU3Lˆà!z… õDl ñ"JÄ f¥^WB܈¼Ï":…ŒHëb:¼ˆÆбC”èìÜ¡Häˆ1²Äpsg¢£ëX3Q&NÄÓ¡abÁkƒ ‘D ÖsFQì‰5±à=D}hMM4!*’Ñ/ÉûƒŠñð’dE^„ µâSÄdUÎ>(:‚É!&3‹XÏÊtUâQ‹‡¦¶Åx颡±‹tQÎŧ(@øWXì‹×æ/Z›ÌÑö^`$Œäð0* x£µqŒiÑ0vÄŽ•Ò¡bvìð2:¾ý]"g$Œ©2F3põ—b¼‡‡1FÕHX£jÔ‡šÝ9©ÔóNZE´ÿç¤åÆ«³ûFä?tÀ×áFõfuPq\F'Í8Nä蔣q4qÅ1Úüãh øá?Õ1ÒüŸì8[@vÜŽXA œ"î¸óÒ“ØóŽ7ä蔥-°czŒƒë1=‚Ç wŠ`)Ë0aËÀ°ùrMfHÐbžB‡|…ëOzwëywm%È7Ô2ŒsRJNŠ›Ì¥nԗ‘ ¸k{©.£¿˜V :*HÌ0 ­ÄoºG‘ɽL&ôñ0Óoƒ"À Á%žÓ ?Ó9{H£éô”&Š„šªqcM’ë5%¥Øt´H’I²M’ÕÔÈ—´›8.«‘º,8é$ž´Ý~J+%»¥!%™²ÖƒT,B­Kf镪SU@Ù)¸EÈ_Ñ$xB"ê)ž'\˜h´¡z >íé*Á'€¦º—\+,¡šÙÈ{ö‚Tl&DýÇ‚ñ”\ ú“^RF>§~(—’†¼KQ2¶™©ˆ,LýhD£šd"ä¬r')rƒý¦ÊÔ"}Ù‘’2I"“I&EišH­Ç"a$ÕÄ‘‚$H’²‰6¤ q› e†a’¼)LÊOe“D…p¢’Æ 9eIåD”f¥˜”4±LÒÊy—̤ìqOX‰OvÉ<É–j(þ4$p4•¢’D€³JRÏ 4xÀ›ax' 2¡Àâ92“â_³c<Ðj!N†R‘‚‚*–vqdÜ@‚ ÒST¸¬s!DE €òø¡o&ìÈÿX +—ÈŸñ7 ‡SÐbbÑr.šPÊã&¤„úN ¦36' ¹Xòc|œô"@l×ý@!õå€(ä3X^@ä°/€”N*®‚Îð$‚d ÔHƒ©@„˜DY ,•Eªä Ër/Ë~5§åÜêÕ@ð VCº–8 ¬î‰$8ÔSÀÐñÌŽ«l$àršÃ¦pgGQ6ÀXÑ·ó2¸Pî$PŸ:IM@ PƒDÕðbi耰I m*oâ†JÐZU§…tª9z]È@e:ƒ¾d•érC´OI  œ¹ÎCdÓù$¯TgDTr‰ªR:¤ŒQ)VRJdG‘’'ÔƒLSÂðÛÉ«y%ŽÎ¨çõxVöi0-$d1&^êB45ñtƒ%c½…X:?ßȯ) E¾¬¦pa¶Œ|¸!d—ȦÒÃ{XÐÙ%Wç{¾‘’&Ïm\< œŠ˜§ó(jËCz0£Ê‘6Èò(*œväè ½ošôŒ^{$©Moé!½”úôªžH½z¦^½¬·R?êíá<"@ð @NÝ©[€ Õ.Àüu‡ x.`¸€ à(€ ¤.°¸@àX•pÀxð\à¼$P3'A=¬åì Ô«s?¥0ÑO’HNBa²V *?¬«hUVÒÆVä=Ág“ð N€ P70‚L;9ä °ø¢@`Ž8t” /˜ø,X éð5À~Ñ/â§ TÉfªë$ÁÚ„›0³bª ‚˜YÌ €4Ñ…p?8LÐk>dÀƒ(Këx*E½—2¢J è ãsìÉJY-ë t ,RÆêH{ëd­¬Là©PI!ëuµ¬dð$×Tã[Ÿ«@®…æ@×êê[µ«vã®5<Ö?O ¨ü€ æÁ!óêÑý¨h^¥»è°°"Î@ á,zê0½#"à·¨J÷!N ,gt* )Áp 7…˜|˜÷A|’™qaxî"PÜmQï‚Ám\û,*Ù@ªOr¥°ô%“˜L¸¹¥ƒ„$a#¨~E¡ T¬?“;EÈXËs°<¢, ÖQl …˜O’| Ó‚)îh‡ÞWâ‰GE„i#®CûpŸzç.Þ€M:Ÿd“}QŠà"üÁ#ã$ñ•€*LŒ,’ý ’ft=&)€¬ åd&ŒM¶–@jaQGûL)‘5ÂÐ`Ö¤W©‚››•ç³#í’K;Lj Ý2ŠlJ¤h*,+H¬lA)0–˜,? ®èÀ1eMSô~5…ð%0•Þyf=€À‘RVA£dÁŸ$ê™MH»T§x]` Û×CJ@ ø–ñD^¹Î Ú§ë´½µ²Ï˜€Üã% ¦º´¹¶×’Æ–v)H A)]Ú Xìl¦À³Žt[–%x”S&-X¹‡Óέ[b©(UNãÝ–DÚÙí.q·1ƒvÄÛÃinÏŽ¾õ´ü– L×FÚ+]Ó¯\›ÁòHÂÍ+²Ôìùd¡ÌSP[_KV ËŠžÄ)ZVÏééðmú¼¸ë3ãúÎ’Äq“Çõdƒö^ܱˆrç­·ÿ¶ÏÌÅX©\/-z­•%ª*[d+U_€ h¶\ <[säA Žé*’,ŠGKÈ—lÙM™Î²MVHg½*ûQyšŸñyz‚[Tqìê|)¨@È´åvÒ¶Îשkfgí¼7 ¼Ý¸;wënH,º†xycQ¤" H¼Û†ñú”KrÝîí¼¶¢ðÚ]~¸oëÖ€R¼^Dò–Ç»K:ï|`’bBÅë6xZïÿØ´—Ï:.€yå.ݵ»¤è0\½+O‹Ã½´ïº!é.,©’Š¡…*Åñ,pô÷:ç týªø4·év8"®"|a.æ)¾d¬˜Î¥´}“Æuƒ£$ üÒ˜– |€eÂZ(OˆüÎêOxlú¿´#ènÉdÚ“ü8Gæ€*ɶªêq™/ñ¡„X¼3À±žÀÙ6pT1‰,Þôa­Ï}Ù(?-( ”6pž²¦¬þ•¤ŸöTY*c È¬G{?pf..¸ $ Xø/ê¬!X˜@–|‚™Š _7E^µ`˜#€i/ &ÂT…D´|agp ÆË—²ª‚“L¾¾6e&ÂÆÀF I1€(‘€D<–i HÒ+ZIñÑÂòc›ÞÐeJÉ–SÀ HPq†Al¶Êjeû„†HÐi„:âÊÈ0AÏäŒ:€© Ibp [*ž””Âð.Ãçì.1 <À4âO¤X OR,JXÝpàÝ’t†æÔS£\Ö.2' È–«I«å”ƒ³8÷ kyañ”á¶§¦ Ûba2Œ ¨±"o œÈ¦¥’ÀtVädi°€éx-†Æ  /@œŒ@1€FĈº 0Ê6;okŽ8}^éôUf¬wzRv寖3÷Ÿ.Ë:…êøÒ§õf3)-:n3êøà¨s´±Ø¿oîn}nkç·’üùErêàMœEwή)<û¢jp ‹163Þ °j_-¸?u¶ÕÀvçj`²5îï¼ÛÍ{oìRve5²VÖ1¥Yíè‘¥uÊžÒCSlÞ ¼C·úæØ&0ðq ÊuVkÕÏf@umÇÚ5¼x×ñz·áz©uïeÊ×Ám_ƒmQ=½‘w^ñßûD{l€°G–ÂfØå9 é,±§ôþ–Wý›M_ïOí­=6}–¹ï³$‘ìajsO6å.’…ekœðb¿}n̆ÝT` Ðì‹}ªáÿ΢Z·ßµÉž…v+hY‰m[‘´§´HaÚZÜiƒµuÖÎÚ@vím¶»Š¼d*«ÅE·mÆǓˢ¶ÑtÛw7æ]dšÊøÑ|[H^Åm¤;^•h3c~ Uœ !Š{,7r(0Ur­âV '–Lžs”R$—Ïøv’Wò »ŸÏGÑgûc=¶½Ù0ÞÓÝxGW>ÎTùé^¯ƒüo‡»ÀmȽ°HÉ%t+çiÈ¥%÷óÙ¥€Lçd1Ÿõ8/gÊLÅïbžî;^ÿs–éãÒœƒÚ,m7(\f3ؼx74ÍÿõÇfŸÃJdÃÍ)Ш ÆÑ£Ôå½oBvÃìWFæñœÙž%Lü]%`âšH©Gá^¶Êœ¸úù BÍ}yµº›û'ÿ¶ ì¹I@QÝlúš3ÒM•Á€UÒ©[V®n>ݺéêXN诹Ү“ª½Í·mÔf* õñXÌhð.±Á¸JŸïrxÈæ¡%~D5ö©aõ«FQ0Ròô«P8Î…< €D>’B Fž '€E¨:Øa&L| 3€D@á›'Øž?rÕFVGNú }¤KŒ•BR°ìéä" È”‘H®„®Ã'ÅYˆ ÈI€ýJ¾á\¨)¬…ÍT¤œs>²§üö¸´%gi|Ž z‡ÙÕsð(ÐÇÞ­˜‚ <֜Õ•>ÄKÚjõ›?3lN¥×ggícY~ä7ƒU’OÁ¸­Ú‡!÷,Ìs¢ùD~±õ®´Òº\F sGî39‰äBÌT*órfȹ–% s{¹Û(M>É Y™cn“>¦•ŽOÆ<{([t5Úg;TáèsÚ£ò®XFzêÓÌ<' d@ÍvÏsÕ~Ãíý Pí…ŽÛápoåË‚Ä/æz´<IfÒ±°Û:§Ï,™)s¾ÅΕÆ<$ÎüG$3k”Ö«œ`»7¿1î½µëqI{[û†M·½ÊŸtØåƒö}~] §t·kå¯n/Èìâ W,àn“‡{lòÂǽ¯$÷SÅÜ“ s/¨¹}I÷ƒ2¬»MÎîµ]¤_i™ìÝ.xOÉâÝO7óˆŽÞ'ú™¾<Ÿ{MìkþÞ´ééWÞqó=}ßKz‘Ùò󹿓ùîàü&oí~/«y_›¼£zð \¤xx ?™7’$^3søjܘ?shͼ6Ø x… ŽúmköÚ0~öžø?6€Æ|lnñ-½6›šÛüši<ŒWξ¹T'o]ã±}x?Ý" ßR1€¼pŽØ×œØóP»ËÀß!¬.wÈK®RÛ£¹ä ò,\yÊú^q½’×ã`œ«ûª3é˜xÃògO¢Më ÍЫ*ùæ‰,M[¬Ù>6ÖÑL¶¯ó\ô|Hn!OžÒ‘â>ÂÎÝöËW~D)îö¯>÷YV§Ê•H#Z»¬G0'ŽÊá?å¹ñä?Û>ŽÆÐ*ÿr˜ÒK†‡MääãðµE=áZ¥õ  ï$?~;ÙHº*ôÏ¢F+ÓOú ÆnúvK:dW¥Ò·md‹ÈÛèþñÕ¤iNÎ7Ñ7 ð|K¾ÚÎ;ÞÔ¯ºt™|Ðuòô^Ê‹zܞ驸—×ò¯{>wùEþåüHqöˆŸ6OöòÝ«A»eæi2ͱ¡ VVUÝQ͇ö)½Ýýfgã)ZÌŽJ²PŽ€¨Ï'ÑçwÀ“Í{™vôý¢KzŒ}Í}<|¿ô¨»ð«n=ͺ½~õ¶JÌô&\Ó±^NçUB4Îð¾€ë¯“õ ˆ”F?ÊVØQq]é|¤[L!xð@Á?Ø]Ñt:)NÀ™ëçÝ®‡l2JRPfÏ¢¯ßàÀ~ÞñeŒ×VP”ÄeÀ)ÆóÈk¬ÙwØyR^FÎùx`ògªAyèoù}^}æž•z>žæfn…|àcðÍoص…Z(ßÇÉɶܥ†ËQoÞW}gú-¨ßÙ–jô`)XÐùm+QŠìçº-z¶ç†û©wºÈT¤)¿Ÿ|wËeeŸ 'pz¯~÷€ÚPfôW2 U·ÌijX6ƒµ'l—JÜ€çŸ&OÄK…Øü€1@ê9€³—¦D€€š(Lô r2Ú©tÀi§-~ÐV€G ìÓÌõ6¼‚§Åª1ØP¥ÈOÀó•ÐA‚šœÐT‚ÒY(»™€ Ýã÷Û(W+à`Ëi‡çQ J‚‘ˆþUÊ©qXZÙ–úÉK´…)£¢µr‰R-xÇÍm²œÝÆÇÕ‚§ u•Ë€$×ñÔ‚‰œáÇøE4–œ.ÇŒeÌ 1H ê`ÜD4œTÐ[I4U^xeo)r Ñ×¶òI(aD@˜÷ žrmÜ-xפq+Ç(傪…Ëñ‚uï%©1eð`r ¾€!÷Ìgý "7ÅÙv^Þ†„ `Ò w@ƒD@$ØÂ B˜süÔÒØ Ö€nÜíöaŃ´TqÜ=x£åƒÝ-Gúƒ{Û(ÈkaCXd¬„áϦ †ƒØkÑ NƒÏ`|–Rr3ÇDH z`™ ¸`Bá3(‚öÙO8UƒÅÝ¢¨¼`ÍP¨z2 1GèÅ>ßôISŽ c]¸ Œý0!ø€ä]3·¥x S@§€g,QÏ“$aê2ûvjå(¡yæv1.n¦3¬t|á¶a„SÞŠ·á]ŒÞC6¢iëF7ésXøÑWé÷³ß~'¾x«+1Z•V«Šj1Fq0òÔØ±D0Z0iX¼oak¥€i +1ˆb¨Õbu)Ûê°ù)J– ‘A(Ì*A –)çñô¥lƒ˜"Ma*ƒápˆþÉw—m¨X9*N@€PKÄÓ¸+ÂTÑ—Ä4xîA0D8*ðVzŒ,NÁ÷Àg’M×Gvááxøaa*òÇÚtÂNÇètÞœ è9qÔ uøÕ†5 Â= Àu`ìðÔMyÀ—(EÀûþAä_pW`ë~øØ`à¯uˆ‹FÿÕuII°äÞö_}–ÿ‰~bÇÿa%þŸa'#VO7ÝIByœbÞ‘Câ€*À ಈ&„9b žµI÷ÅØqyà`’¨†Ya"…cÇžvj sñ™á€éŸ<ñf¤V¿‚þ0Â×M}ØvˆO˜ñüõ*;Ý€•€?Ý®v Ö=D5ª u¢‚h?0ˆN!Jˆ¢…¨Ïdˆ"ÃC&ÞtP˜*ƆÑk#"óÇþ•ˆ À‰ŸÈ@ð† zÿ§ÿýu3â`—!Úˆ Ž˜êˆ`8?b8$*Š.Àbc$b_+^Žˆi-vKa“x’pˆ]”N$¤]dW%BÍD§A׸þv¢Ý­˜+ $TâHéY‰€!°äyÍ¡"Èãñ… ½Ç,…Ïb˜å†ñÙFA`H#ÒCÖ.uñ˜à¼\ˆ€ƒ9$Õßð-Y†÷©B¬M±×–Ou—›ñGûa`ó×eFµaa³øi‰azÇlƒp%Hž4"ÎwM`Væ ž@ÖÌj\‰7ÍmSÛ!S÷(T @ Põ‹Q0…cȈ­¥…¥f¼Å[ @`2Ê’`À2¶*Ø 0ÊÒUÈ8x¸{2Ý}X&&ˆû!ô—&ŽP„Õ rob'æWs"RW'Þ‹â…Ø«Šj‡ˆ*!"¢x؉íY£˜…¡ˆ—G°”Ô0@‹h)ˆûߨ¨)2c§˜Ø%®âŽËÈ£b©($Þ‡ªbaèö}ˆ³â&%‹y §\µŒðÌxÞ‰ÿ™Â(0Œ–YyPõ–W°86ŽGF9–’c®%›]ø^(+bZOâ O ŽŠb²x9&Œ™ãÂÈ|uŽcI°h,N‰ Uøô÷팎ÙE2âz3ã@0ÙAÑ©w˜ãó8ºUœ£4¢^jcÉ•.Ã#cXzƒE¤7=ºŽäÃèÒw/ÙeHÒ鋚á|–1«Š6—Å}c2ŠŒtÕî3àã ©2Vl‡#Î(ÍpÅM̈E¶6ãÐ2új½cϘüŒbâòÙ9a„¢™X4¢‰ÞÛ D- AÓ0="X÷ð5Ežø'ÂbÖ((nq¤¡8¯)€>Øh"ºÂ¤¸«élƒ±P)fˆ—â(Ø 5"87î_ ¢¨è#‰{#ظ*âf­â§ø*^¨ãiÚÁdð†8žnx€â.ýãë.v±žåxK²ŽÆãæh=zŽ-èè°ÅŠ7¡“X+žŽ·b…E;H¿dÀæ8 “°#˜';ÊÇâ+i}ÝŽ6äÉ82ÆþbïˆC.Ž#¤÷äM“Õ£ä¸<ÒÍceø<šÑ£9‰Kº‹ºäõ”evÛöHsÔc‚÷ÈZqbÄXV>à#@Ùù‰\Û£û¸Ÿjú üH:Òö£¶‡E¢Œ !éP²^¤ßføO~y „øX@žëÙÃ)6Ejc±<`Û i@NúÒ¡t`|݇È:Oa‚`^`dcF„¡)ˆVdGÔçØøÜÊ‚‘ñb Á2P?å°TDcÓéBNûbÁ¸š“cÀFW%•B$¦W’ÄßùBòwvñ ÌES¹A@àÁxÙlb¥ý@²_m¤Ð˜Hž‰ñC "Ümâ°¢G*1|¤Q§Hun€ØÖ*(  Ö%úŒ£I¦ˆ![h€,\’:Xg‘IvŠ›¤¬TØy’[öeO¹’ m†”RŠ¢ôd#JpôZhUI%XS-Êp¨åXú}£•:þelצµ•hE|†[–•# n±–¸eㆧ•[¡×&_Ñ]ÇœãXö¡OeZxüI•;dîÇÞ“šãR§lXzJ V ®Y†£è\î‹€Z\9(懅"]y4j _Á 1à‘AÔ'ˆ~¥{Yà(utÐiä‰ò%ÀD_޼~™Ô1bÝ¥R5æ—J `_ âS7HBåŸ!)W’—ÊiÉH:’bce)I¦s_À"B– f0Y&v•e'¹~’uc¨x7öˆ¤")y*r–©b‘è7"‰#+ÙLf“}`°'M¶Ž£uùV*~£#­%2“½™,Γ:fLÍŽ„#ÀGdÖ—Xψðáa€E¸ €¹²!ª…$!²Dí‚b²^´*@vxO}#Ù`q\&„x‰HB˜D#8`%{¹WðeÔø_¦*¦‚ ýYb‹ã¥5²˜e"Û8bvÀÇ)&|™®éØ52’ `àµ$Îg­diWcêxE0Yd.TÅ"6I;ê_ãÓ9‰c–LfZIšyÕXqõ)¸0€ PB-u÷%–y¬Ý[f|eÉßD!!f~ dægqf¦™Aãxù!–—sd]ùfÆ@A^) ú‘Nc9g&ˆ¬æ)!Hî™JGeé`úšü— ‰Øš’¡YkžN‹&ײROàÚ£‰oEšºâ8M^š×dn–d¾p¿§ii†šN&©Éº”{ŽK&ˆ6Sfªi5(°æ¯Ðœ™ DétȆmå$©°~¤J g¤y!··[Âshe¼nÆzj& 9W›ç¥¨Ðˆ²É²ÙWÚ™u¢|`:á—Bœ¦LLÀpÜ^ e. @s´œÑÍ)s:$zÀ €Œ%g~ñTÌË9¸œ'gʹrJ4çà.Ë QМ ̉D”$-çÎÙsbOÒˆõ.' p‰!´Y€@Âb`/ñ~N4A€P|ð~–‹ý§ahÌCD ¬l@°dÄ·U`Üx@ xèÒ)  –p+$JÀÀ4%¤ŸKp`Y€0€ÆtÊ÷YÔ‘!æeωÿù¡Å'ÅÛ “d8ˆŸƒÇ6Ù~ò¢Ž‹‘µÔýXEÇýItµ û' Ñr¢ëbYýÃå XèÉJ†¨¦A•µê†*ñdÙî~JYDb—“¡1‘ÝeÅêá[èƒ74š—u¤¹ ,È™+(ymȉË&Ђ¾ E@'ƒR›…b·Ù-à ,¦J{^˜ä% .<–¯'!ùafŠœ¤:b"'%æª7®˜hß…ºŠÝúJB“{’zò’]h0ªLþ˜óÊŒ9†®Ž¨æx†Z“i¨ ѵ¡Šá*OÆ¡ô¤I‡F”(úÈuä#ÀÖ‡v£€¨ Jˆ sÝ("ê(¢ÄD#úˆF¢“h%z‰f¢›èÿùAz¢ ¨ß2Š–¢§h*ºŠZ4U€+ ‹Ê¢×èu²}öXÞg.ªLŒ»hTê‹BZKú7ÚgÃè¾XŒê{ðÃåŒPŸ‚ •b؇žCü…«€ŸFc~ÑF°R AëèSÉW‘³ -3†wH¯H…ÃlâAd&÷XFáµËB°G,Åœ7«LDQHR™“Q™Úq«)ÓÂQÕØÑo*W/h !GWQ𶿇KI‘¥Z¡é˜À™æaÄt¿uÎÇ'4Ks5@QÎ C`üáÆÁþmmB@:UÞš»hq?ôžŸÃ?çÆ_´Ÿq_½_ªÊ¡tø$Yænšr‘›UæˆÆY@sú`áqØÒ"?$óÄB‚±+v…æ¬ b ­#óa {ÊU¬&ïˆáAœhC ñTŸ–m^‡œ‡èžÃÊ¡|Y+²é5/61Kßë0ÀxäáŒ_ÄBQ ¦+$˜„ɵ5ð…C,\ÀL9SÅTæ„_¨^/ÌηX 5„˜á| < •%HH¨‘©ÒabsEÖ`xóAA¶ Ÿ…BNcšNT·Ä½9«˜Vw@˜0v|K]mBGuð[i5Á û±ÆB¸§ttå¶ã!ûpG8kOêøÕ„t 'ÆÇuH ª£Ò^˜V@À)ž |ÉG—˜çÁR…l·’iR‘¼¦ª#áJ›êS•П¥¨úÆtGªu%c2À ðj€‰ŽÀ}>!’VzÀðè/òW éC OÈð »±]|Óý¥«N¨¥l2y2ð×ø%¬®Áš”¡fñ—ý¥~…oó‰yˆ,Çj Aªt iê¥ù)«êF™n’v´ªµe P±å”—JP÷Q-¸T%GlP3–…¶Lk„i U5¦£ ;æeÀcjF´GµÈ-åà´¡É_ÖµJ,)“ƒÕ¯’ +À*dD{ k m`ć5‘Ùt‚Ìga¨f…ÇUp?´…žBÅ÷IOÏK*ñ™ V¡¦@hÌhˆ £Ê¼Â-Œ Y?קȧ’ÍÔoàIÇÒ¡ÛÔ…4+Ĩ2ÙNiciƒÅtÊð|ÉÕëtiÁc.€iiÀ)Ç©ñx[€döz|¬þе&¯G léÌ–%kP‚i5;Ò^[œí¥Ò,5Vêˆ¯Š …龺FBÒØ?ê}ò†=Lƒ…_X]oV~4kd‡>¥°v<ˉæ†ì.Û©ò6!å Qu¹ç 1Ð.„ìЄ0îq"Ô0®¿¯‰˜¢ŠÖ÷©ÏÌ%Ï9—j JWi‘X$rê‘P$‰¨ $BUðªTU´DÀªÊÈ%€èÀºŽ­`€0^€  hWÀìû àˆUISU¼öI×½šÛ+ëÊtßkøšt5[$@³%:è3¡èÌXJ4¦ ºÖ™Ré .› ¤CbŽ‹¨k¥µ%|š’£Ò½Ùu*}¨aE×¶ª€¬@‘Ú’˜*‰ ·Î]sk0s §£W‘:%ÞEªÀ­bëÕLG¦¦ Â^Í{˜v'læ•ÂÒ­m¦Ñ˜>Ì›"šüp€úÑñ³Dc)„ÙŨƒ!˜3Kdšd97UòôÐ|@,#ñY=¦va±¶¨É&:Ôâ?à#{žáAh àö–ÑB|€çÑ)$AÉhiƒö=çL €2”¡kýcf[µµù6Ÿ)#±P,µÔ-5BèRÆhá› =ê Cx}l—å)`°—JèÀPú$= S`~``d% å ‰¿J ÕM°/¬›¬d©––†¬Œè‘IÕºl²ëMGÑ,y¥Ùçô+€ŒfÙáQw¬I›‡nÒVh©± ÿA˦,ÿÇ-›Ëv²»l˜eËÆ»l.[ I”ªUwH°!,]VXVQ ©¡xåŒ>Ãȵ«Uš ËNS.•ÒÃ&¹'uÎ1[{Í]æ'3KâÐ, ÔQ³$UE…Í–T5‹z ÍG#Õ<ÁÁ³P|ôÌGàÑv4ÌRqßl&KUàG!Ä~¤Kí°ÿÑ{ í–`•ÔÝ ;rÊÝÔQÔ)hìó–¶°rëÃö*—kᚘl®=e°Ð­óŠ´@D®Ì:™Ž)ÇÕ›6^¬Gš¼%ðbíqÅYû˜µ`íPwŒµgÀZ«>n- @¼F˜ `Ã8_òA%wVr K&(TR‡X/Ðj>u¦¦À<Ê–`ADcybŸ1È`=Z°jÁ7Q‚'bÐZT²ÿYU,Ç9ìMr4(pð€¾ƒ¥§POt¨V…°uÈZ]EU ì £¬„ʰ2 Z „0€,óM(ÀïʧˆÒÒhEY-„ -çN<ñ,»Ê¶X·R'0+×ÊÝrU. œšÍ‘ðé2À’ÍXé²[ˆ¨Ž£J ¡qÐV[G·"ÔËŒë´ðÎI@b&’.Ë ‡Øã-ÓÊ/¬»Bs ¹¶0 B.GcÑ2?,œË sK*g ¡'"xvbÌsk €ðs[. XÀ ë,ë{ášI”N3@ì* È sȼDÀ7óa 5‘¸Ì b@˜N|FÌȯ˜ìòaÌË®Ö6·/§Jsyð§(Í™HÇ|ÁIìòÈœ+ŸÌKŽÒAsÊy€©œZ ÊÛr„áe™Ë5³?!2ÇËÑf°pŒÌ Çé¶+§Ë[s¬p°§ƒ q,³Ì£r©üK½ŸÚ`Ìl6»4s­\-»Z×l¨-3ßÌ5s82«Íáòò-ßMó¬•@4ί2ߤx-c³T0w#ÀRÆüÍ´Öè|/Rrç9û3íòu¬<ÅËgËD/ ö²ÀŒ[ü úò%5s+Šê¬;ƒ³¶\‰p΢²nâ5K 3CyvbQ@¦@!Ê…„à<3os˜³Ò¬9kÛè 8ÎN³÷Lk¥ZsÉ ¨0ÏB Ýiw2ÏçVÜìY>¹Êé|*K¥§ß x~u!cÊ,<Ë@sw•XÏâ³T°¤]@áÜ0ç̃ÎÌ3ÍFs<á3÷Ï¥ÓÐ|(ÍIó6Ç4+ÍO³3&… 5cTs%z&–XÖ2vͧ[í Ð]@º<8ÕWêóé†wºÍ™CÍ ?*týüwÂÍ5ô×ì7ÏÏeÙL<Ñ,´2[Í»—W†:ÓÏ €j{Exý˜äÐt³ùìΘ¶GP"«Æ•q’‹s.À_Çûqo‹Æ>§|ÇÆª±c, RÀk¯Ç´q€ÜÓÔ]º1UáãBV? ËÃñJ#ËÇrì0Ç&†s ·4Ó1PÉØq ‡4tvõ+á±0ÿÑæ±'ëq{üÆÏÌA÷0÷qK“ã)²MGȶ±¹L ïÈ'r‚ìØ0ÈAr‰ü GÈØ¡ÏY!çÈòÉi+YµÝF?ÇŠÕl ®ÁÆÐ1| ¸ƒ¬!€ÁÂìôt4@óC"Á €0!ÁnppŒ08€w<> ãtî°™]cδÇ`+sc.ÀÅÀ,|c­‚8&1cõßÊ c& ?T‡j’ïÎSŠ…²] 6ÿ7©ƒ…madÕ‡šBaFPSÁ•`Ð&Â3üž‚K€6ÈÏ*ĪÂÄŠ˜zà¸r@¼€`Øx¡%ÁâP“®‰ê–ÖPÜ.@ ÀP+Sf–_ìÞ.€ ÀPƒS¦AG­Ý ÀTí3ðÜÔv'“]@ ¦-ðZ¨]².E öýC”Å[9¦LæJC xD5ìVÛ¹ÔHƲÞÄ{Ó [Z÷Ä AÀ:€«àc¬+õæ}dPmÀËpcÙ³ñR_¾¢Mï ýHúÐ\RàßȤ®Vïv‚m.óÍ ¶o ·#–vH6QOT…Y=l7õª­ÛÜP,’í۱߻r ñ%O MAÌBVh|=·¾<‚ÝL‚“›ž‡'Ò r¥/K*„It À²}X%Ùuáy{K[×2¥ú¬;· Á| SqaÈHhR‰vCFX *ÐöŽ›V8””F$Pî*®y² @—­iß.Ã7p|wÝ*#%­¯Lš×†ã#-„¿•Ül ‘˜à#²Ä“Mœ‡ÅÄ!áB8(sà¥wÐý„x‡7¬l=¿á„¡=_ÛÔ³ù¸B¼Ûõ)Ƚ´Ù¢J×öެÛ-D#Î7i 7Kq-φBÈ(ÔnDøEÖe‹â²d¬I«4–•?TßÕxµRM\ë&[‹°À áíp•í’¥öÉ{ûÞ’wðí¢ñ©g[ݹC!Ù¦Êo-Œ…™1^|ßÉ÷òÝ.ßÎ7Q˜ÁÞSÃì½Z)µ÷dŒk d5|U+àÇ€egÞ¹Ó1VžÌ'QPPì9îÎ|e2’7›]%·AY—Ú[fÄKÄ(@5tKöpXÞ0‰™Åeà{Ö[ð]q†mAÀq‘G Çü0ÄBµé8üvœ"ªeŠ›*䀪ÄO³éE –²¾„‚jj—WøÈ2O&Æ è½)¨#–Ò!4 ^ü¨ál½‡é’üÄQ¯’¬jñk=Ûû¬hê[ ”3å//»-!*¤ ô¶i×O*LÞjq<\‹˜’|è1š„$Õ2ßpÄ¿_|m먄¿²„beˆgYç¡_µDš²ç¡7QÞœUP9Í} |2b²n+÷C)^-1¹¦>’+,ù_~‚°Î Ò÷@H½½¸Êý˜ÓL¡¸ÈQHh|Sjâ Êão6a{Caõ}á@,Ãã9LùDJnGd1SJ4î)\6%¾WÙ)†§—OT¥øÞäuxáQC•ÑUèR18l.àݼ²¹ä€›Úå ž… ¿¦¼¸-ÏXàwª0n™Çã@q=Þ‰+Úɇ>Î)T0DO\ ‡×¼=‚Ä#yï?ü ÒîvçSêƒ~ æua¾ÃЩäKa&€_ì”"9ZWÎ0j¸{“,±žïç/†žÕ;˜ •¯’ãâ`9ažëƒ§ã̇©ÙDyÑ% *Ð è­¢ŽJFy=²[ïMÖØTއEØÉ:@÷¦ïícu;'&¤ß!c-.uÎÖX«mîHüydqv ª×û>’¸sÐŽŠ(^pWÙ÷)¾Ÿb¢xã¾oÐiHs s™“ |Ò²ÇH}HSLÉŠûiÉ›; X$°ø©.¶íÅ!øíÛe(×î Äín/ ¢øÂ×££îεÎ"™p0"@{QÀšÞ*“ª–JîþYëõça¬_*¾{\èM§Ä;‚Çtˆß4+ Qs{S@Ç¡™[ÊÔ’ús9˜Ð;S^`lƒG Q|ñjᦠï!ð†Þ»ùnr+>ƒÇ^AÐá³ óᾯ‹M¿nV{ï±î¾<Á/6!€ï~Œ$ÎÌéK¹ªÈxš®?dÞƒ»š Õ~ðØrÏ’À3ïŽs,÷Ã.î.ºìlÀ{ÖÍ{=¢dCïŠÉ=Gb‰Är3"ºÏ&ö#{F 8ÑûDΤ'âi²y>±oÃz ¹n pÛº`˜J7º ®Ì@R¼n]”Ÿê’:`4s( VGtãä0+jc»»s÷ìAµ¦àÞ;áþ¹—â,ü &K$RPº4d¼­¨†àY8“.*á³v÷½/ÚÍûâ.*»Å½nÈx0 {<ÝÇcuë©…ý±”ÖË»_®_ßË!_ÈÇNŸã¬Èóíé ,ñ8ø]üÀYlËÛö¯`”×ñ!¼«,É?íö~zÛŽ ,/%WÔ|s/Ãïc»r#ÿ ñ <ÌÊ¥ò”\»¦ Ã¦Šœ3¨ÉcTŒÎ©sÏ»• Gñ?71¿V+.À®ü¨ìP À@#sàâJõ@°Ïà™8ü¶F%ê‚ü;KXµ¦Šó?Ä$‚̼c7Ô‚WHl‹æ­#`ó38€DÅ·ÛDu kK6fÆÅçY' ÀB˜7,Î !ÊLA—ƒöM»·õÛD ÓA@3–ø±Š?½!œÉïRÒ52üØ;Éç¶aŸ&ã}(¼^K¤0À`,ÃR{ #uàâÔB ñf¯m§0{“pæÒ ¶®Pö1…wÅÒõa‚]¯-T ý¡"N8ö¢°@ÚwítuoÝ_÷ؽ]À;XÁEƒ‘4, ]0Û€&ðÆO€<° ¥Â^€°ÁÁ Ð3œàßÝ[å´ì=ÐÁáƒ:#Ì÷Šƒ!?¼Ó% ]îeÑÓ,êà4ð“‚Õ`.P’äB pŽY—°R²µ…¿‰^?Q¡YN¸MAzsßú¸†¶µ¥ºð•×vÄD±ôâ.£F€­ÿD\Z@€Ðå÷®ø0õc1åá O4Ÿ¡¦pfbr ÐÙ†¹@ÐYÔ}Î úø+î…›áY´Ä&³Ë´¯4Û¢P=d~Ûtßà…ÉE‚J о"íjëã÷Ž@’o⢸HX™ÿã¹^ô’‹è¶øþGš'=8¥FTÒ …)Æv—& TGùI~‹[ã²-p¾ÚÒ͈%ñùþJ@PˆúGÀq5XxõY0AW¡33*É£ŸÎDú$ €çSÆ{þuXøù&Á88mn9`¶š~7“túŸ¾ž¯Ûòù£>ÝUêgú‹~£?2wúMX†äúS„‘pþ©«úl@¦é¿úž>lœç‡ú}¾­ïŒÌ°É©ÿ@ç©>ô$ÂúÎ>¨?ë‹ú¤þ´/=E£ý8ü)¤Š¹DÐéC¾~)(ì³`<üÀAM éþˆAa#­>§ßì£Å²>z îKûg:]?ï»4W½2jÀééøeJ=3ؘé Áv®Þ}íÀß Û=“ zec‚Ú Ma°yoMß 6Ý`7H!Á‰"4?EPßwePË…;ò d%!ËtÚ@%3Ü„8wþQ q&»¶”!~ ‹åÊWáØ\äN@Ý…Hè‡ýЉ OVC[,í_ª>[NÎô´¾zOƒcú4Ê`ŽýÓ~@­”tHÍI™ýù–5n×Þ!€²Ö· "šÙÿôC‘ª ݯ΀3ÜQ|O6?‡¦h¯*‚ª’­õNx—ÖUó,MV†1÷¿Æ`.ŽÛ´Å]sÊÙ1g’UÜÊ÷ ôyö±Ÿ¯*’w‹–ýŒ¿^Ó”…qÿÑ/ù£íuù_þA–¿,fƞħáMlÔ%Kî¬x_ö=°þïæÎõÝœÝîn:­þ±E#WPm–¿Üö¸¬îM~#ˆhËêô³+‡ô`~v ,'Õ¸D¼gt ópÔ=KŸ±”k“HÙQžl …I A ”å…¥Aú\ Ù?÷Sÿ¨ÿõ~îúÕöŸÄuÿQLTþ+ã?æÁüW± )÷2ë¿’ûo¥dœˆÿ•ýl~Ì¿5À±-° \B[ýÊOç§»‹ü´ø3?‰þìw…)€UC€0:lX ? Ž ˜~B(£êKú•  âŽµŽˆ ,` xÀábqô fLa¨F„#ÂÜoDf†¿Ø½ŠŸ–à·W+¸P„â½/ØÛ0ðñT vÛ´€ mÔÓadÓ–؃™_D`å'#hù}0¿ÃAŽ@ ¸'¨ú1ƒ{Ø!zš¥eÀõc ‚u°ßT ÂG€¤ö{4'×lYR©Ml{‹úœ°€(–œúRd äÞB,ѲJ¨³ÅŸ’nа\Ê£àÊ—Íx fødš’¿’?Ìñ¦­Ú:È”b~2\†{ 7×Y{GŒêpb¤ ÔŠÜ®›°©Û) r ”O‰$P¹—©ƒYá\ qI»a\”M¦à¨p Ùž{ª="Bß´Gc»„ñ:S:±Y ÅQqłƎ]¦šÛ N CÐ’õàk$±U©x:7òXw9A‚1P(Ý[¯-bO2•Û3P LT ÅÖo¤ºA Ê¢ LâõÌo‘ J ä`"fÊHý]°æ… +°ˆrÖ+µ|£„EHBÞ1ˆÜ …ƒ {Á\#Èà&àc~.7™ØŠ¥]ð†)úÈcg4РωÏ`èŽm i¬1 E£î’sWžsµUZrL Лl}ºz+ 7Ú˜JC†JSiˆÈŠcé ÜØ§ËYWhÓhƒ–1» _ è„KC"P4VN>µçCàF–<¤á)‚dŠAþXÖ 0V"ó½ù 2—-Í:¶K»¥-,µ‚ÙtðGX##å1ƒûÁëXà@YhiD¹pdRgE0-9†DàÓ +Ö1ÅàYŒGè,‘ÙÈxƒf¸ Ua.H$¦IÒú‚Œ@êGcÁÈct—ÿXm,Aˆý(ØÇîƒ- êpPH(,”€®c_ªrÐ.ÐøE§iS@1˜›À+àù‰”ÖƒÀ‰À% ß’ÏihÀ˜@Ìo h(Œh* ‰¿¨Øl®ì³DxgQ v-)/µÞÊ«FƒÃR~IöÖ>lßln ‡µó ìÝ0:§Vê‡cu°:¼n‰–¿Aw¥¶ÒMÁÝÉZ˜‡Tá$a Ï‹eÅäªcª+ÐÐíJ%?H Ã>«œ¯ð¶Ðpc¯±çÌ%mÏ—‚N~€–#»˜SzCïˆTaÓnƒ ,(­ÈþvXîB³‹aUA¯pì> ÞB(‰B Þ6.” |¼eD½Ç”lj,Wc¹ÜUÓ;MCɘjY:x¬vè¡ !$#&+Läå²rx!øÁ·Ð .Ô0ýÒd”%Êà˜O€4Ìy¨LXŒãd8OI~uö4CÃÜxNg°è òÔvLº>€Ð°YQ*, K…ˆÂ‡» Ó!/ " 6~低_›€+P5¸xÓ,…©:p@ (@ù±?…s0tÚX@|°ß;B ”6¿ªßÒÔÑ4D„Q ÎtÀ|Ú·€_ÐàSÔÔ1>´¡° ‹``ètœ~J¢Œî ÒóˬþÐ~ӿÑK€Â|3¤±4#@ Ê…K["P,› #ðª;¸ Ë:µÑ’²™‰Œ¤9tM½f¿˜Ñ tˆK#¶ pQ÷`¼G â:!È%è*%lï?öKÌH…¨„émɘÃèá¹€Cô)'G?Y€ÈeYˆ–Q )÷ªŸ  €–¬,1G 6¿ ÀHoç9غD®®²¦á`©ƒ°؃=<&;•§„2¢³ÏmÅÄoì²ÏEoWbyŸà¦e]€°CÑô'_á>"ƒ,<â`‰°@êtŸ¨?3¡ýÁµ,uàP;ŸuõŽ:Þ3€Pî×Et@(|ÄQ4:›ø¡í$ “ UÈ83^ѪEݰd8&ˆÈÕ=P!ˆ LóôdhDÓIp0Ç ’Ž…£;FYm%“*sͶ´Ä@M„(m!!ê“0'D˜‘/)%A”vä‡ôC^’åH†8L,CÅDdbsä¢äC yŠf4)Œñ˜M¤Ž%Rr¿boë®âA !Z_È~r?"ñƒ8NÒ!‘£xH‰'yDAt ¬“Z™w’d¡OüÏ̹‰óC{â=©ã•Áö쓈R@ âdåx(wi Ç€€[ñ‘üo ¤Pü0¿E&DQ|4{(L14 —$".‘ðD× ¿Ä<Ԁƌ6…9 Úuˆ•—Àׂ†ÈB¼æÙÒCqq¤(ÿÔ‘‡ED×CqégsQžDŠ$€ÀÀGL*.ˆƒêáqùG¶aîAå. Ò?ß¡ßxØ=ý=þl|Ä­ ‡ÆÌb/ÚÙ|åÔG?µÆÀE†Èû!åøˆçŠ»ÆÀ¦÷²Š'4åR-4ÃïD§pUü)ìõxÀš}úîÐèZŠÊCÍØ¥ÊùWûã&ÈÿˆŒ¿â1t£±aŒÿd7ÀÍ@â(—»™R”{7+#>Î\ÑeÔ±ÑÔ`pöAÍ ¨Æ¬ÈÁ9Þ O6Ö››Mg{ƒ¾‘-Žd5&ðÍ@i\¶P*ÞÒH'\¢hQµHâƒ)¤ó–5[9g kZóQÄ…)‹H9Žk±#qA\UpÎ5§Óé€àvlTÏÕ¬ÚSP„&ôý5Úž жf¶8Â)áÐjt‹@žcÄÆ®¨ï‰*žø7à®ÓÒh±†xù)Ê]~‹Y§KÐã²@ªÜh „8ÒÀž"ç)³Ä©O°–F‹:6ýæ}à@ë-6…Šű“úˆcTùã 싇þ_jn}ø+0þVYr¿£ßïÐ <œ¬œþ(µ—°â҆èú)8y \U‘B° ðD@¸¾|:ÆÉŠ‚è›qõú‚Œ4®c‘‘jóaA알g>A2 €*žý €UEGWNT“UÌqIYŒ]EÇ鬘¬+vmVHF MZ‘¥±V¼‹íàpE´ î¦ISW´+‚ r4…Î^1ѲS˜0ê‹fÝ›&Í`1JcX¼(&™‡ÅÿAçïÄØº0,ˆƒ("‚¨_TßX5™ÅBÍfñvã¼1*y w ºÐb QXóEš._µÅN#¨&ŠÓ¯Éy'@8MgÔX©ùÞ,l¨UñÿâÀ\L5þoŠ‹î››:Yña5Fåš‹Í'1Ïo#†Si¤áÐ’Lº»R†ãâºX@@×h; ëƒCwÛø]œÆâq.•`@ÈlÆŒ¿&ŽÀæ‰Snì× /ŠE G1‹S{ù0*'¬Œ¬?¿‰1¦²hÜ3QRŒZÅ/c‹Ãõ˜ü%qbŒeÆ#ÅÑò‡d2úy\ '£‘ÇhÑx9~eŽIÆšãþÊ%åBtá]Ž;G+×Ï‘æHdrµ¸È\UF ëOÈr=ä6í¦«â- ¨æ:”¢) 4С‚¬uȘyîÇb‡?§Cï°Ë¸b9Òÿ¬ŽØ?)€øíGÜMAŠˆÂ; ×tË>ðFΖě>EfóuŽžQ1€h‰%€jKÍý *@Åâ´"+§B¢ÉLߤC8‰†”EÊ9$©ŽFÉâ¤Q%9’FXÿ'Kfƒ˜zŒ¬»I4£Ö£Ì!‚Zœ%•ºLb$Ö£EÉŒ„3B#áŽÔH?£ "äð_¸TUÊDÒCÀN±øèE¢%Ù’ˆ‰5) RíqrÄ…’!fÓQŸ&-5qðäa"ž+M6©ûÓ7±vÔ$@''J½GÒ wÔN|@½+:ó¤t’òÈ*Ã<ó8ö$Ð#x"ò õi@Ú“ø1'ÅâAÑÕ+©(B1ŒEõÑG±r¤kŒ8.7Œ¨" ‚ …Tœ”Ç) qãCi‰V¸±)J‹RÿC³S$˜ Ž›¡$òR5@#Ô¥-ªI1üÇTŒ[ÐžŠ—cõp·s‡]‘7¢Ž»äCHíÑ€ oX và@¢ÃTñueD°`ažhe1ÆiÅ‘­8àq.ÈýÈPÂò.FD¼,àÎlȈ†r ùO >Î!/)öÇ+£Ò´²î;"dìT9=‡]“@ùÇ…DC.kF¹ [ñRÅTØ%v­äŒp…¨Â\¡]ÁȈ/ ]‚Ÿ…«Àcqßxh<h 4>³uá¾ØÍ!çdèGÔ»M©'š#ÎÑæpsâG«ÈSä>I&TÎ)Õèyž>PãÙŽ—"®y5iâê9dˆ{NO—±ÏÑYĘÂአÂHè8yL‘âªÁd‘(i¤4ò~T;‡01ä%%Ú¢âõD{^:yYSfúHY("öïLL§Nm €³ ë˜uÐ_i@I‘·xXü/ö‘N;œËÎ8$³3!ØìÔø\ä3Ó5r¶³ÚÑò8y|à mGÌÈ0Vy ‹¾2Ä(,Ðúðúˆ9œ-hÈ'YD ‘qÈÊ‚y]a3."W†IGd\±¤P š,ˆ$1 ±è‚A´aì’CÅhâF¡“tñ PØ éâ6(×Uðq’ÆqPçe*„Ò%‚ˆOÆšã ¢AöËCR$ùAÀ×BFú¥ÊY-"õB¤“`ˆ|-$)+&I7ã(ã’„Dúqž j.ØÂsá9ŒÑyŒ7É}£R”CUxäì$y|:¡¤Ð–¯(T òä8ƒÂv|ÉÀSò’•ò%’zCÞŸ|á"ÙdüCÞn B¬¤XR‡A–ŒCº€BgIµâI3Ù–¤Õƒœ rH Pfá© ²KXð’|¤$ð¶ÅúKÞ¶vB!ýŸá6¹˜œû¹o[É©¢p²"9™4"0´’–É»ÆG(¹ð•Ü "·cI4äq49þKD¶ÿ ŒHšÐ±Bü·’,.h'Ÿ Óɧ%r³0Œ aÌB²%¬ga¬›ü<÷’áÉ Ð_rÎ…›¤M”zG†IžPØN®¡—ÜAι BÕŠÏB (œdLÎ{Œs®å× 24ô¿1éüs‘‚=ÔÐ#@Mƒ|üzKaˆ §ƒ"X ˆ¢z‚™Øð¾'6 ñ`fCӞгƔ$r†JƒC=-0Üúµ z?ƒcÐàn(P±(ùsÿ ÖÁ|3ÏQYNxŽ îˆŽú6~cQÆ£-žµ.›ÈŠEù£ì ™çzFÍTÐIÙ¾ã䀂ɇhH̯ñ4d±:;/:(Ö—¢¶²Y`Ú~n½ƒ]Ëá%nûQ* Í….· R·v]( Ý2 […ÓÛ>é`¯KÐéá4v5;å û`¸"¶S.2&1†‡8Üa ¸m”HæGÙ ð¨”cJ…‘íéàáuÎjw_J¯M—-û€ñŸÀoJmö8fÆòÞF‰Ó#@qÈ™‚Jä€(•ªŒ2Rà6¬Ô(ÓàeÅ h"Ð’!Ä~$µC÷§Ô HìG1›H€ì² ¥,©óÌÚ ˜’:¤eS)Û”)ÊD–$’%À[Y5â„ý(9Z­º§­!ÐP%”euJ_!ìT)šÃ>0Û0>ž†AÖ˜RÀ;“°Â†;:K°^¤ ÚÆ ÃBzÕ4a¨ÖÜùì[†³LZ>˼| ·l™€ŒozrYŽ)¡_àÛn—‡¨l¬•Î bj?è95žZ€ºÌ¡ªÙý >‹"ÜRn [þÔL G·åÞ²Grýúð–"½eÜ’p™rÒk._W„ÁåÜRy¬þ.ó–oËÅåäR®P¹Lµ-!—™K¾ePÑË%D].—¡KÂec°¹ I‹¹®œ|‘KÍeß²´v·Ä\J.g—R&€xaE9¦ì yìL·š„¨9•“;ËéìŒx,ïOW®r'³p@ü(OªmÁ+އ›z$šÉ Xö¸ZÞL¢ÖšÚ> Oúµ"À†@¸Âz¬0Tc;Üôr¡ÏcQnÂØeÄ„êZðR–¡¼<€ÕV `šóܰˆíÁ$h϶Û7b|ùú»ø¼R•@FYà[67ó_:gÛ0œ¢¥ýw€ ,(0_g&Ëþe`ö::@ÐÂfÿKÅC€– ]S`,ú…; æLiQDQæÉh(L’Ò‰Q¦‚q…•,C€6@U®ì /®·3Þ¤.'WwƒU˜,ueKÝšÈjWi.³Ä+^VA«O›7Bú@üÆ2øåô燩@øè×"g÷ƒüåë зL]Î-}jÒ¾}γŒy»,\.Ô˜å22¦âRtI¹\ŽÁ1¡_rL3fßruYº¼c†ò˜mÌÒZ-‰ycò0«”»KL¥ž@ ·„;\LζÐ)AàZÔÝÚ…Œ„eÉð‡•4\´-w°<8ÝUg9WÄÛU¾/M'ñK.&õG¿Æ ˆ³ð CFQµµ¢ã °¤Ât@<b*n§æecý[0 ¨ûˆ^ÕÓ–S!ú`÷@‡æÝ#NGEªØe¶ z™î`frã„@fâ)Š™¾Ì•›æ‡Ø¨jÙd‚1¡–*Væs#%ƒ„x]X¾\‡4ÍØà ° ‚™3Ç èÌý`S&2¶«ð²dÞ™š‚x¦:“É%WŒuÔ¼–•„ céµ9[Â'ìt˜ºæå&ìw"dÆ ZoT¦¡YF¨DLÈž™ƒ?Ã#ÌwÊÏü•¡'†æ·Levµäef4It@¢ Ù@–Ù9»h² ™¿Ì}ÄãÁöÀÐübR3D*30¦q¥ ØKÃÁ4¥™Œ™æ½²ìÒÐò1l>FŒfÄl£éÒüiÊ4Uš,MQYHóSÖÐŒ¦ÛôkXË!G³§iÓŒÆÜ„š M€…9rp¿„$5_š'Í}]JsëÕÜ›l-[šùJ æÁ†~Éaê ÂL‰;~…Ÿbô6‚ûf‚5©š‹ðåø A .L4¿zͦÀA=HÀükâ+*3MÊâ¬y‘[j®5­e+Á­&ßl®Y¿´k®5÷šyM„W_ó¦éØ$jÆ2V&ù@ñ!Ñ"ÎLmvu’–‰Í0ÀbS|ù±(mªðX ®MÊÂŒBÁ3!6±Í©&¾rЍ3ð|íö$›k€¬ffó­É[shú5˜ÂM¢f`“"wÊãzØ5›_‚ØfS3­ÉÔìhÆ5U ÍrfÏ)5#Ô(Î3?#2QAL~À»$fVÒz‡yÅbãÑO€,ædJ CàoRYF,Ñù°vXÌM˜Ÿ‚ÖècT6#”Mî&¨¿)€È_Æ2¿e´Ì‘8Ó• $bd* Hˆaæ Í!˜PPZ•¾0kÂ’…Tqo ˆ±Xz žwÄi• yó"l8X[ ¥ÍXFB‹6ñ2]†gA¼­î´ÔÜË¡l4fS4&Píf†Dª]džcL€ªNânkáâ5îs8X5N‰Â³q ã|Ï•xœMç@c†ãršˆœWw’SÉ3brNmœœ!#(çŠrÆdÁbq/-웘K-XpdŽ3s+3ÎM`±‘) (œnPNáî!í&M°j8Û´(€L ŸL Ÿe8-1Î>'0ËÈùú±¬9—rÏÌŽÜúµI·Àr’èör@fƹá‚ðejZÄï6w4qÉ¢‰ÞY"(ÑF"¸‡Jg’sŸC23ã59ï‘OÎS%édtn(|n§¯ÙJ3vð(¸Z28‹œbNK'þ,fÄËÔt–-8·Oç¾n/—ð’ ­*šw\‡wAa?" c Í2»¥æ(S(`½:-˜HYç­Öi2»us!£5ç˜r±ÀÍñê¾l𠃺0°p±-1hMa3šÙ_@˜z…@#)Ø–_˜ÚÖŠY'Ôße! ìÛç˜4ž¾L æ•óàYç”tþ:˜2‡ç‰â)x(ž]K '›“ÞN ü©è”t0΃pÈgˆQëNh4Ç/Î['j™€e>3Yž"„²&@Ú9jÃ< kž|Í%DÓ®éíDÈÁ6EhE'AÁÕIÜ”(<¨:éÎ1§Åóç ±z=÷r4Ï)^Ò³?WÝŒh’ܼwØM:@p3êyáŒP=s›‰ÎÖóÈiéÜçÄ;O;lN*ªÄQ±@úFÌÈn)NƧ‘õÊsê:mœÏL'áŠøõ¼V8ß,ó×®€mt©p±3GfìÎó™»3ë”á4s†¸Ø™Y4öf3‘É÷l(0Há¡ÈÕ«6ß  18ø„fçGÉãT¹e'Ž„e ¡çÂXÖü8•žV0³gÚ3¶ J hZ4}š N@ÓF")îÍ¢h*€«ƒ¤Ù(’pŽàZ™‚N„ç¤S¢èLÉHÑŠŸˆÍã,“§é8ûà-gg4íç¯3¹”[iVˆP„MÈA<Çw²Ïa`žnÞeï’]†àÙ\_Àö9]MâèˆyÿDrîs¸::=ͼùP3;^P‰‹·sƒvîü~ª;å eN?ÞæS € JìA-1¼L•YF³ñi% ¹:¸‡ƒ'æóIYùtx..4Ï'¿ñ݉êô„ÆŒ œL1èÍï<™Õ¨GïP”Gí(ðTùUP‰Aõœ1£{‹óÌ ªU@ƒîå~wÖ;d§ÄJB‹ƒ¢:-1uÐ;hq‡ÊuvB¡O!Ôê°ÊD¡©Î” #WÓš„¢îDÐÂ`¨ÙŠeíϲžuOTgæÓS° í„^CÉÐ"(ïaúI@“ƒâBUžVÐ]¨ŸÒQOH€J€$‡0BŽX9Á³×™B ºÐ0(ên ºLœ$F›˜¡pg¨Tמ‘†ºAõ pÐ&ª†Ñ†æAõ¡ÍN?(8tù©ývBI¢†ÐÑ =4ŠyX‡¼öX׳ƒ;ôÛ9¢ƒÄìD÷ öPX'>tÖ©•…¢9÷ ¶Ð9¨”ó™) ýB¢E´mItʹ‹'´B?Ÿ¯Ð7h&ÔÖyæÄuÖB¯¡Ñ&’h‚èîÄ ‰n:•SÑNA¨8ô!“5‡ÖDÓ¡9>Ã̃ ¼`8‡òDÿy3HLAg(ÊA«„Æ:µžMQMhY” ÝÜD« lÎò¥§@˃Y…Ýês† ‚.ÑÂMX…Ž)‡@8+è«`ƒ¶¹S†–AÁgЫÃ3´2j`ƒ²EÅ¢ö³•(´%Zm‹f:e¢pÑ@hó.:Õ±Fs¢:ÂhOÔ&ö}„b„££<¾‰MB8j]Š®;c¡ŠÑ×StƒM˜?›wÂN/f‚¸fììqÎO¢Åzh^á:ʵ”JÈ£§JJç˜31J•ŽšE©£ ‰ÀJ4ä1ˆ&îT0ÊP”h}ô>šæ<|J—š( / ä”d똷ѷ¨%š¦*ZÊØ*%‰ïœEæžäí4‚6A÷r €Àï®v§tÒ’C™HÀ;§@‡´!ÚÛD>$@;Q΃†”5J¸S:Á „žÒÍ]s”îÉ‹¶;£œÏþhÌèT'ït@¨PÈ dŠÅà Ѽ«I* Ôd+ã£X{qÃø4„;^›å Ð&»^¾#”'O–áLW!r7E h‘áÆ”—;ñPæ ×íœ}î°<'Þ3TY“($pâ+“§ªƒù7'ÿì*ô,É d2bêç8ôâ œíxy§Êãâ}ªðùïôœnb™@O‡ÀûsBÿ´/avš®¬e´ qvþìœÞ„ØÀªó]°þ>˜ ᛬sô†!ò:Å9øÏK'”æÓ¤fNJ-•Òæ&ÇSê)¡ð@71¡F³Ä%&}`Õœ`5c™˜MlÙ«”ï%Š ¼Ý¶ÔLòÙÔ-úì̆C¼ eæÃðàývæðìS´Žéeçì(Z…~:Gå ÀRÍ‚¢ô}Ò(5lúNž£NÑ÷èd&Í?èAy™O4€—  $J À¾fÏLVY¼t^J!0xª?žOˆI¨Íbø õ–JJÑ£RÍuçªôƒ@Ði"LÝšÛœ©­4YJëÔ•F›ì¥-ÚL¯Tð+]iK1ÃÒXéÞdñ¤%Kr-}š*³xéÏ9y‰Á5UFÜ¡ÐMX(ßdæô,C"„B*S°ä•cºîľøL.SX(/“„y¨Ø—ºL[¦žiÔT:3u—)O.ðR_&¿4[†1¥u,@2"«i´éTÊ*ÝŸñÍŸÓciÄ´ãéëTxÆLï¢ JçÓtYê1—–¥r€ré£ô\*M—2F×¥ÉP—é¡”ëYò0štü¥dÓ„ç³ á])ÌH ¦¢»i±´pÚAÚVFh¼L˜aΔeŠ1uu>=›Þ¸”3\ê.›ÊMå—˜÷IÊ u \:£h‚È-€ €yÐBKÜ5ZÄ:t²Ž r/À”`8€HÍ)ôK9ÕšNE_š0C hãsêhêLCž!.»B jõ[¬G";C›¯1çÔnš#½….M“ !èfânaÚ*õj*N7›cSZéÇ“bzªÛš5É^OAhØ4Â` <€GµgõËcJ´é™† Ÿr°Ú›à7I…whtú,ÙÉ9XaOÕ@Á°GǶì}îPôk•Mÿðórz 3~*6‘Ÿ–Må§w`e ù2 XQù_þ²ûy×Tþ99¨ßÏvAø³)`ñ$JgÞ¼ôgà´VÊþd`–PwäÒÂ&Öå}âÇ„q@;J¶³¦Ùé`)°ÏÉvg>7ßYk(0vø ýËy³j\³`&þ4• Hs '!(³ôê,•‹6HIÒ‚ öÁǘ+­PH¿£LÐðè·Ó&÷àðFÞ(?€/êŒôºäŒŽÎB«§jÎ5©b   uÐ:^‰(n.e›Šzm¨˜±¼ÇžhNMªç<š¡FÐéáj4k©EpNC… –˜'*òMhš m–.H墀T˜•:”8zxªiéC{¢5½æÝr4)Šî¤‘¢KݨÓQ\è/…ÊÖ[®¸£_SA¨t‰˜k´PË|§ÃÒªtJ=儞ꆠîSÍa'±=Ńʆ©-Щ)g#fanhö¤**Õêµj F©XQEê÷¥”àH=‰þR·fFM°Á­ñ9+m{ŽO½šµTZÍ£ åé3õˆJ@¢hÐé§6µzgÐꦦ‚ §ðÔD*QðÈë¦*9wЯæ ZSÊMX= p­Ÿš«ÌÚ¥)á,{ ó›¦7¹#_0x˜Tð”’ì€ÇRÈ»1±® /³dXBT­·mˆ*“ü.=™S ðiø´˜J¤—2̲´’JE½¤zG/fî,j=% –ãkqKÁ¨RÌÃqŒ:O%ÜYcb¤<Ñ5*b:Ú}£úR­§.UÊfUT7šå£ÒRÿ£Î‡Tè‰ð]g†EQ¢½TZ'.ÔPšM”¾Mc¨uRÐ)â„—K]§n3¥›ÍMéiÃSJ¾l°ÍB¥¤RËJ^•)º=½ivM¦®ÒUêÙ¬œêñ4›’O£ª¼ÒÍUs)ý˜þÏ«nc)²Ô«©,E‰NQÿ UÔ›*Âì~ ,<Û(Ÿ,¸jiªÓEÔ«±ð&´¥¢²ŸªR5ÊT½‘ºG隸ÐêýàaFÒä›}0«Sª[UûÀ8MCdS“-MÐ0§CÂà²ø|R[ÔL…' Své·”öÒ}HQäªWS¹ÊÆd®–Öz« 4À°T ,xPµÐ ˆÎ|YàmgÖrÁ®Ê1‘„š1 ÑÌ‚–CÅ®š2hJ3úBÕ_BÜ"A9§‡ Ï© tJ7ý¥žFX✶ñÁ~@I}izC1«6ÕªªnêKqC€/ ¢U¡j—­@÷[uuzKM©rPKLÕ ÕéD«žUÍ ûІçkµzº.MÜEN3Qïh&yÚ@|ÀRcv…”g Ãzåü°~Sݨ ÏS];USð.¥©"X;rQh)ÝDóàSmŸÊSŨ©Î Ìa“ÚÎx¶•$žï¬~ªÀtµZ# ±öC¯§²Ðëý4\É*+“&ÏŒ¤;;A÷-MzãÓ²!ªJ ˜Tv uÄùtÙ®.´Cܤ"A¼ëyËv¿øM½Mc ùQ•¢Z«½|ž)~ ÒìåÕV;g Ϊ ôÁYþDœ55ã¥O ‘1³Á©2ê€Ö?g˜³Ól !ð,{˜¦F©¤ÔzE¢!Î!£ËÙ‘@ù¶=kš©TŒjµtæ|pÀZI@©VLknôþ9;³~2éž›ÔÌ '÷T à0u´Ú;1 P‰Bú€V9={¢­U…¥¼À[ö {¶jÕžy¸g&€[kÓó½zk­¬šX}¬)V+³5ßV¨)ÛÝ2ÌV6ªô|†ÿlZb2­—ÌYµÇj`Å&X?˜‡M«à“ÇR¨ùÁo€‘åÎ)kºu©bm·^O-1­VTéÚ”ÞÚUY5«Ê<…WcBo—pÅ䎢BÕ¬5µ ‰S¬\I©–P‚ëÖÌàZbÅžJn­Ñ[«ÅÛŠ ­·:\ã¢7Õj§ ÍyGø¸RY×#×^kÉUº>Ã;ÝÐT®±VÅCTjÿ|˜ùõ¾z%MinµÑx»µ²ÐÖ–˜iÇ4Rš8¶²Oõp”UXhÎMª}ƒîG­§%×wë®Um€š‚[3« VåM‡ÙÙSœDq×›k tk¶u }4=%f¼Ø j5‹åÉ”¦jƒÒ¤îKB+`Ó÷NEj^<5š NïhÔ”à9™P3¡š Ìujõs‰i=hZÖOk¨5°Ôä3&Z_SžVÇ*n5qJ-CµR^O•òÖ%B«u‰ðjõ¯ÈZIg¬³íõ†ªxÀ€ŽDR§«S@ë”Jئüè "GÔ2ÜhÓ«9 ¶žê†¦¾WFÎà |My[«ÞÓ]ÙaÒšáT¦âø n#ÁŠZ?² gô¹\Ü+­ÍÍC[3âú%u@|…üx±•Óê ÎsGM5•.['qÍÖêÙ³dJ-{² ”f©×mÎêu›£mÍÝq[W®fW—«%õá*n…¿’[ -¯”s«…õŠam£6UŸ¢PÎw«å5Þºj À6\°0W«¾UŽ×oýEZ\×M©ÜÕëZuªº[£M ×KMªTŠzv½·N;1 èE&YrmÝ·Â5mWãPzaãêoú`gl®WÖª•GúTÀ¶ÍN®þ•”k·Õ{` ·â[E2×%šÔQ}„eÀª[‡°#Ö"쩎ç*Cë;逮£&ûÙ¥³èÚ×ËYvö­ó×ÿYýõŸæ_yºâR¥®ŒÕ4,¯s·*6™¾A_§~ ÙéñóP;½æNÍ~ŠÞéæùŠg:°özVQðÕxêœTš–\ ±&'ì V `JyfYߘw3ÑçÒœG¸`n`3ïÈÌ ¡ËFÍvNÃny–,ËðZ@¥jT}”ÝSâ¤4ò >[¼Æ4¯“ÖÉ«-vjZ/u™Ò^=tUS_+F ØêÕÌpbL÷¦/M³ªß´_úx¹âä°kØ÷ê…gšl]úMcƒ¦BÐ…) sø*tŠ:džNð*Y'ú™,•±T*3VÅM3Îà ¿|ï ˜ë; \é„.ôGÀø\òšæ××A8aßýwŠŒ’«>€åªèÒË$ËŽ¦5Ý‘³9,áŒ7»ÈÖ-M wK…)@V ˸|è5¥+̓lBVúÚ­È.ÓP‰ìt5 []¥cr.cƒÙˆBö„ Žvd7—M€ÎeD–ÖyĤ®Î1U—ˆ.Ö%o0%û§XÉR̤¯5Q=æèR'kºÉŠd‰S6Y¡,&'‹ðɶZ²/YÜeˆëp)c=±Ò&§™¤)…Àrê@5E`]‰SšÓò©oûk%mÚL©¢8S_æÊ4+KÍÄÞ]Íy¹?A‚ ïZêŠ[¿:Ît)e–͆¯`ဠȞ1²A2jÐ,ð:Ô¼m8á°L:åf O[ÆÜ„•‰M_±äXÊêäõuÆ.£½2Í^¯«³VÕ‰bh#¢üe˜Ùáôóµ­´î)~´U¯içì¶ú0¬ÃNdK²„K‚lÎLº]ÍzW!âX€xUV^Õ‡žW!déU­èzuiÖ^Õ‡¾W…¨ñUÏì·hj¶ÍŒN?¢¿K€u!J 8g!©Ñ&çìæŽÆ 5há\ýxZë©2Uáãªl_„8‰¨•;¦¥Îb£6ÚÛ›´_g¬„„+§s¶óéÇ;N¸eñ§çS£¥zòZ·wå›`|8ŠM‰(f­ûØô}žO½ž‡W”¦µªÊh=¡ÚRÏf´X&¬sÅV4[)ì?q˜:L ‘ÿÓRÁü¬ˆV𜛤Mí©ƒs¥‰Ú\‡ÕUßÚ½C‰6L Øç0P_o‡ @A…öZw a0Áúƒ@ˆé„öšæ©äh/³HTØ«f¶wÆ™åŒJ Ù mfúi0ÂPáŸûUóÍÖó¥ÉÛÄ ×2‚…Ì@õUŽú·»Dz0íªþ35†ASpÏÛV+û³ÔÔžçŒÕœ‡vyèPF¯lUȪ±ôlöèÓ–NÄ´"ÌØA›Ðô¤ÄÀ ‚—œƒÞ?LO»@µÞ=_œfÕ‹L\î¶Y¦¥“:Jwwã6ùB™ös'>ìåµTÚ3€Â3"rwÚçdjž¬T’ë§ÖÃ?tj¯+M³*ò !8øœ’e1j´Í/Áç”+;BõÊfjŸ³…ÈfI¯ñ)‡•ÓÎT¯ñS­ Á‚*]Ë W½©Ìζ©»dUË¢uÕ 6³Ú’)ÕÔW¿\wbØ´|7­o³W«[¬þj§¡´Î°ªx–K‹3€ýE\k,f†kœ!_ MXLdønä¡"ß›4Úv©íƒ…03 ·UníƒÖ[{=«É’do²0ÙÎ¥·ó7»H["àæš 6_Aä€A`š ÄÈH}¨3¥hC•QÙRµ®Ø µ.PðåÚŽK’®…ôä±Ã“äâìnÀv[xq^˜Ë»‰Ý‘­˜‘ǹÔöV´*®ëiS Á¢¥Äj¯ZÌV>0 %˜bNEb7L ªÓÐsÑ¢UFh£ZVêÜ,d4ªåÔîBCªDS0Ó¶~iX…~Éb^³Û¾eóæ©¥Ú’jÇþBS-ú,d$!ÀÒâK“±‹*mÜt¿:Q˜Ÿê6×UÚ ž\5¯à³µÕVk÷9Ž+ÆÙiT[ªM;1\ É´›­qjƒ]Ù5NÒ*ž:Ò¡©ÛTmëª-ÛÒÏ^¨;[›íør€xÙÒlc¶ª×½ƒÑö-D´ÕÜTpµ•[¯mßV¸ªÏ|¬8@GdLX{+ö ·’09lºõ‰À”q”²€ æ >+6t«–àjÜ4< 7á´ÐÖníœ|v+5±*kÌZ‚³vw³Ö&Bë¶ÔÚ ­µ[+ÐÖvuôµêT~-GÖ°®E¥¾Gw¬Î3¾-ØÖbGºõÉ3ù™éŒ,@êöåJU}Â20§™7%zb¨ç†è"P01›R@û‰Z¸7‰ .º[‰í¿êHÞ¶jÙ¶ÏZYí~Õ ½Ú†_¾³Øï-”\‹²eîõm xvY›šjguÝ&í^œ³µ&lvnÉÇl]¦-ƒf#âY,Hൗ}qzp#ªïYË­k#‹Q¼ÜÊn¶”ÛÖ¦‰¶g;­uà¶EÛÏm×6h ª]U¨PÝCÜð˦ÖÕAsø`V‡îkÙü'¦Ökk²,‚bm…²%ÜäX† ðÝžjɶ9OÁÙ–j“¶Õ6nݶÈÍÖ­«enk8íáÞjñ¶¿MÁÞVt;¾%ÙY`·Á-„«pû&ô‹!nñ¦Š[w ã–m븬Bnm¸’ÛN]åVE‹ÈÍÜÆhµ¨úWÏíѶ+¾Ù™j›¸æ[ufj ½™[ßb`Û·/X€w‚‰ÀtÔnÏp9X‡f·”z…íÝ ~·ØÛ5,G¶x›¬p¹M ¸Ë[&]óv+­íÊFo¸´Îk­LÒz ¼™új¯gÜ[¬æ“ûäl—²âB·Dܯ­%·]†ÉMgšnÑ·Oõ- V[S]݆rß·=ší`~Û`å`Øo•9X n·°°€à\ ¸e\.—y;Øäå>oݸw[e.?”™;®}q¦c)vaÛ‹Ýn#G¯åyüÆ®M4ðkËÌNû?‹åÒa½,l\­_v™“-]Îf£«ñ„Úlwõ»j¯#ëìfÓ~$ƒ=RϹ˜˜Ò6ú–èUÍà6§G›£­ yÐp´/Í ÷8[¤5ÈWÇHZæ¬"V„f÷L‚n]¬T»ì‚'·››}ÂîÌÌv]ªÌQ% ›±«–bôk«Ü«Ö•[€å*]«®ÂÛo--·ýiË]Öâ°”·ó\]n=7­ÊÀÅçJoƒ¹Ô[:1ס«½=›%s×­ûÜ,ì VÙ*P€z2\›°h×'lµÓ}‘+ó ºY[t×ÝíTW³à»ÝÕ²u‡·“U°,äôx[ÀýêpÓª9[ÕÀ.—¬ÛË­ÕþraÓÛa®þk[{ÕÓfu‘¹Ü,öøÚ‚õæ=W¬ÎØo驎;kc=Ô²9jSAB»vÑ6qCx…=k-+ÕÏ2cpÑH`sJC˜Z¯ ¦” ð-¢T/ñ¬*7Iâ’Ô|4¦„×’bª-–0 üÖmêÕáNm7¨:cOÁ‹óοu¨ßÞÍ»fÞ‡sÌ"H©W=*¥ î’ÏÛ‹ó'öÛÒöøz%F®Û±° —hÙÈH„J—Z²*[Ó¬ª_…ìvߪÄݸ*F—¶Aµ¹×–že䲺^*á-Ô•"9Mº+6jȈªkÕ¥ºzv÷µˆÝ¯ldKûâŒÚ6x\˜ùF-¸ÏAÌåIŇâÍ…©E)¿R˜_€&šµíKà l¦®W¼4‡Àkdöï„çÊs!» Ü«ìW¢`ÖæNp;¼yVBÍ%²Á ~˜ÔÆRpvgŸzmZw­ÛÙ Þbx¿µÉ\'­‡·¿û¨ ¢$,±8VL,Þlðz@¥çBkÙ¶/Z*póøÉجm–i)­ € ­ý2C«ÈÔþ9弞M܃š7»ÙDM‚&m¸NÓ²«>wl›-Ó*<ÓˆFN'®Qì•@±_*<Õ1 Ýnú`é¯ðÚzóh3†^¤dëð›¨9›¶®mË MIáèÕô fýg.€*î§—Š{B¸tVr™ºÕ\yfŽu2ãÌužez½ Pqn@PËèõÆ3½x€îî8‡¥9üy#«BÐW/ù6Ö»ÏDtõ3ç®àY»+þ {´Äe¢bì¼r]»v¡À¥Ä´e:Ï3›Ÿu 9 ÌPºÚÉf‚V­¹ Å·:V fYÿìÙ ÏKçÍÔÍ %Òì®j€ –¼FÑڵÄJ„êt$°{Ì„íÚͼ(8äº6Ë—)Ú·CäÖEÛ•…ÑÚ6·SÚ¦Œ6ðJû[ ãf8ñ°cÝlI/àû@å®4ÿ‰zD € @÷Y"(¶ COÓ«%FÑðÅJ0ˆ|S$_Z‡Ó Àôg¸ù®4«f°=€4´Á;Ôý±uC¹4ß;«Ó×­bé.Þ'q× l•ukž-¹6,ô 'ÌÜ(­óF‹:héîhu¥Î–nL7‡Jë„ØQ‰´ü2#-N׈Zöµfô`î‹Òlâî;?Ø2Àk:XOöZi€½Õz,{Vô,îR;c=Ø}ÍyrGC´Ì‹÷dsÂeYéË„/ž“ðûÓMÍŠSº Ûh™V÷ŠÛÆl\.°«83‰‚FW}ÀÑ ¯òÎÈgØU†ïÖ‰`›^=®Æ^º]ß—¦KWìËb(ÎòD;hðÕmÎM—¬dDu¯¶v¥¢(€Ÿ®t6¨ T"Ò~q½²³²ë2:¦„²éÚ’ßÅ„Øt¶!èàmD‘¡4{혖5»ùÉNtݘ…SÖ¯fð“z°}Ú*lË Û(Ë“ì“êtû.Qqßë'•ç+jÿŠÐž£Ñ_Z¦@¬úK¥ûRuÕdyß®B›A €E†búj`įâ,ƒÖc†ª_ë®4ÅqëÓ D™¿ý‚³’‰^£uPwsêß#©¹¬‚;!Ð…Ò:>˜ÞïÁkLuvó”<|ÉBºÐOBÅÅ9~•­œÎrªÑcè/SËÈáfG#·8ÜÈîA r;màÚ{k¢ÛGî$wswì•›= ä  ^OïÓ6hæá…³z­¶Þ¤lç×"‹‰Ý ){ÿ…§Ú Z!KÆ-y r!»$QËaIO;åWó¹´¼­7ð؉E‡¦o€ÀíørpââãnŸ£QÑ@î¡â Üå-ä>Gg¶®Í ° w‡kñÝÜjÏ$¹Þ0•Ž;Í-ßZså.›Ü(5ô²*‰-zŠr¢ç\cŽh5Õýý$È©»Üni·T°[eþVÍÄ¢ÝPÕíÑ×<ÃŽ¢vG°‰PÖ.O÷,ºýºÞBk½“àh®—Ù{Íuö¦o7Á¥ÝYð^œKb Œs=©õP>IW•·Ñ†f’%=Upj·û 6mXsÁñÙhÙ.¸ì°±BU]Á"´íl8ØÆJë•Óu%¿`^3^þWÿ«)P: JáÙ-벯6Û üÍv-jZ¸;k0·Î»Uvô~sE¬eêsÀr\4÷R5‰› ï®öݢÀ*9²Y­¶\vüýúê/³u>Ú±oZNH£¤žåË ÈYµ/ï7I›0û¾›´ù3…î€ûÛ¯åü2W=¿ݸãè÷6{èôèž~'då MH×mª £ŸŠp)XÛ•.LWG;^ƒý†„k¿#a£0M7íkÓUÎætÍk;]ûjâÎTú †Ï>Ñl¬c^|%"ØD»Ú¢èpk¶u[ðçš÷ÚæÍª¾y'¯ôÞ»¦wæ¡ve«±t¡W•x©Qôn½a¬Q/©W/lêô6ï.5MàÀpWšDÞô†TS½å2Äð¸ v2†ÇF„á4⥆–`çòz[Šá¼°WØ› ö:Î$ÃÑÜÒ«”É sLjH ·ÈAh¯­ÇU ¤ †ýbvW†&D8›M ïyÕžéàüe]¸Î[¿¼óv6é¼H„ßpl3ÃYŽ•n1ÁôÌ™´7\ùøý“ú]ue^кPö‡•—5æ\©Æ”ß_‚ì ׿.ÐîP³5ŬâìaÈÀÔ÷2C´ÉÒÉìºÌ#,/#û–„•¨'áÜïî—í{ŽØZ0I³4RÚ«lõt£?»ü΄ºš_Þjø_+”•Í&Ðh³#Ûlé×'l©¯.Ð|³(]à¬Ji6œ•é&B§Â¿³ªð|U§;Ÿ­¦ˆ‡¿êZ!˜uÖ;‹•(HR”0ⱌxFL#®ÛˆoÄexmh-2.9.0/misc/README.exmhwrapper0000644000170700017070000000150213201227060016160 0ustar valdisvaldis README.exmhwrapper Wrapper to keep from leaving stray exmh's running on other displays Purpose of Hack --------------- I run exmh on various different displays. This gracefully kills any other instances of exmh I may have running before starting exmh. What You'll Need ---------------- Nothing in particular Instructions ------------ Make sure exmh is in your path and call this script instead of exmh when you want to run it. That's all. Limitations ----------- As written, this will not work reasonably in an NFS environment because the display may not be properly identified and even if it were, you probably would not have permission to access it. A solution could be worked out with rsh/ssh, but I'll leave that as a further exercise for someone who needs it. Author ------ Chris Garrigues exmh-2.9.0/misc/query_jpilot.sh0000644000170700017070000000276313201227060016033 0ustar valdisvaldis#!/usr/local/bin/bash # query_jpilot.sh # (c) Gerhard Siegesmund (gerhard.siegesmund@epost.de) # Adjust the paths. TEMP=/tmp jpilotdump=/usr/local/bin/jpilot-dump # In which records of an entry to search. Here e.g. the 4. userdefined field # where I put the nickname of people. You can use (nearly) anything you like, # just don't use tabs in here (see jpilot-dump -? for help). If you just want # to search for the default, meaning name, lastname company, just set to "" more="" #more=" %U4" tempnumber=$RANDOM.$$.`date +%s` tempdb=$TEMP/jpilot-email-dump.$tempnumber tempresult=$TEMP/jpilot-email-result.$tempnumber function thatsit () { rm -f $tempdb rm -f $tempresult exit $1 } # Is there a querystring? if [ -z "$1" ]; then echo "No querystring. Please try again with a querystring!" exit 1 fi # Create temporary Database-File (for nummer in 1 2 3 4 5; do $jpilotdump +A"%p$nummer%t%f %l%t%c$more" -A done) | grep @ > $tempdb numall=`cat $tempdb | wc -l | sed -e "s/[^0-9]//g"` if [ $numall = "0" ]; then echo "No emails found in your jpilot-database" thatsit 2 fi # Search for the querystring cat $tempdb | grep -i $1 > $tempresult numres=`cat $tempresult | wc -l | sed -e "s/[^0-9]//g"` if [ $numres = "0" ]; then echo "Didn't find the querystring \"$1\" in the database (Searched $numall records)." thatsit 3 fi # Output the result echo "Searched $numall records. Found $numres matching records." cat $tempresult thatsit 0 exmh-2.9.0/misc/cite-update0000755000170700017070000000131013201227060015066 0ustar valdisvaldis#!/usr/bin/perl -w ########################################################################## # cite-update / v0.2 # # Update the dbm file(s) that map email addresses to attribution # strings. # # John Klassa / March, 1999 ########################################################################## use strict; my %db; dbmopen %db, "$ENV{HOME}/.cite-lut", 0600 or die "Couldn't tie to '$ENV{HOME}/.cite-lut': $!"; while (<>) { chomp; die "Input must be in 'address=attribution' format!\n" unless index($_, '=') >= 0; my($key, $value) = split /\s*=\s*/, $_, 2; die "Input must be in 'address=attribution' format!\n" unless defined $key && defined $value; $db{$key} = $value; } exmh-2.9.0/misc/README.mybogo.html0000644000170700017070000001750013201227060016062 0ustar valdisvaldis Bayesian spam filters

Bayesian spam filters

Introduction

Bayesian spam filters offer a more elegant (in my opinion) alternative to network-level and regular expression filters. The seminal article on the subject is Paul Graham's "A Plan for Spam" (2002) [1], although there are earlier descriptions of the method (Pantel and Lin, 1998; Sahami, et al., 1998). Essentially, the program evaluates each mail as a bag of tokens--words, numbers, (parts of each in some methods) and parts of the header are all individual tokens--and maintains a database with the probability that each token is in a spam mailfile or a non-spam (ham) mailfile. Once the database is primed with a significant number of mails, the filter can make a pretty good guess as to whether an email shown is spam or ham. Improvements have been made to the original algorithm (which may or may not really be Bayesian, but that's another story) by Graham [2] and Robinson [3].

Applications

I myself use bogofilter (which offers different algorithms and seems to be the most active of the projects), so most of the rest of this guide will talk first about using bogofilter, and then try to mention the other applications or the general case. The first step, of course, is to download and install one of the Bayesian spam filters available:

Filtering on delivery

The usefulness of the system comes from having it filter spam mailfiles to a spam folder on delivery, which is checked once in a while for false positives (hams in the spam folder). Just as on the spamassassin wiki entry, I have bogofilter called after lists and before the catch-all with the following entry:

 :0HB:
 * ? bogofilter -u
 | rcvstore +bogus

If you get spam regularly on any lists, you'll probably want to put it before those mailfiles get filtered out, obviously.

Bogofilter can also be called as a pass-through filter as

 :0fw
 | bogofilter -u -e -p
 # some more recipes
 :0:
 * ^X-Bogosity: Yes, tests=bogofilter
 | rcvstore +bogus

This is more similar to the way SpamAssassin works and would simplify integrating the two. This is also the way SpamOracle is called. There is more information and examples in the relevant man pages.

Integration with Exmh

If you have your filtering program called so that it adds the mailfile's tokens to the database when it evaluates the mail, you need to tell it when it gets one wrong. I've written a hook to exmh to simplify this task for users of bogofilter and SpamOracle. SpamBayes doesn't add the tokens; it is run nightly on the respective folders.

Files

The routines are in the file named mybogo.tcl and is (might be?) in the misc/ directory. This file needs to be placed in your exmh personal library directory. If you haven't already you also must copy the user.tcl file from the EXMH scripts directory and add the call to Bogo_Init to the User_Init procedure at the top of that file. Mine looks like:

 proc User_Init {} {
     # The main routine calls User_Init early on, after only
     # Mh_Init, Preferences_Init, and ExmhLogInit (for Exmh_Debug)

     Bogo_Init
     if {0} {
         # Arrange to have some folders labels displayed as icons, not text
         global folderInfo
         set folderInfo(bitmap,exmh) @/tilde/welch/bitmaps/exmh
     }
     return
 }

Once the files are in place, start the tcl command interpreter (prompt$ wish) and type 'auto_mkindex . *.tcl' to update the index for your user directory.

Preferences

The next time you start EXMH, there will be a new preferences section for Bayesian Spam Filters. You can select bogofilter, SpamOracle, or some other software. If you're using some other program, put the invocation (with flags) in the correct boxes. The program will be invoked as exec "$bogo(spamprog) < $mail(path)" so it needs to accept the message on stdin. As far as I can tell they all do.

If you're using bogofilter, you need to select whether or not the messages are mismarked, because then bogofilter will delete the tokens from the database to which the mailfile was mismarked and add the tokens to the correct one. SpamOracle doesn't have this feature, it just adds the tokens to the correct database. If you're calling bogofilter like above (with the -u flag), you want this flag on.

The last set of preferences tells EXMH what to do with the message after you've marked it. I redirect spam messages to my spam folder and redirect ham messages to the inbox, but you can opt to do nothing, or delete it. This should probably be taken out of the preferences and put in the function call.

Invoking

I have the routine set to be invoked from either a pull-down menu or from the keyboard. For the menu, add the following to your .exmh/exmh-defaults:

 ! Add this entry to your Mops.* resources if they already exist!
 *Mops.umenulist:                bogo
 *Mops.ug_current:               bogo
 *Mops.ug_range:                 bogo
 *Mops.ug_nodraft:               bogo

 *Mops.bogo.text:                Spam...
 *Mops.bogo.m.entrylist:         yes no
 *Mops.bogo.m.l_yes:             Mismarked Spam <Key-S>
 *Mops.bogo.m.c_yes:             MyBogoFilter spam
 *Mops.bogo.m.l_no:              Mismarked Ham <Key-H>
 *Mops.bogo.m.c_no:              MyBogoFilter ham

To add the corresponding key bindings, select Bindings...->Commands from the top menu, and type 'MyBogoFilter spam' in the Command field and <Key-S> in the Key field. Check to make sure Key-S isn't already bound; it is not by default. Either delete that key binding (by clearing the field) or choose another key for MyBogoFilter spam. Do the same thing for MyBogoFilter ham.

I think that's it! You should be up, running, and hopefully spam-free!

System-Wide Setup

All of the above are for a personal implementation of bogofilter, or possibly a system-wide one where the user has write permission on the bogofilter database files. For a system-wide setup, we'll presume that bogofilter is called as a pass-through filter from the /etc/procmailrc as user bogo. Then, users can filter mailfiles based on the X-Bogosity: header field from their own .procmailrc files. For reporting mis-marked mailfiles, the system adminstrator should write a script that takes incoming mail for user bogo and runs the program accordingly. Users then need to bounce the mismarked mail to the bogo user. More on this later.

Question, comments? Email Pat Carr at pmc1 -at- cornell.edu or edit this.


Updated on 29 May 2003, 00:08 GMT   -   Edit Bayesian spam filters
Search - Recent Changes - Reference - Index - Go to Beedub's Wiki - Help exmh-2.9.0/misc/README.gbuffy0000644000170700017070000000103013201227060015074 0ustar valdisvaldisgbuffy is a gtk based biff program, which supports multiple mailboxes and MH style boxes. gbuffy can be found at: http://www.fiction.net/blong/programs/gbuffy/ gbuffy-use_mhunseen.patch is a patch by Diego Zamboni which enables gbuffy to use the mh unseen sequence to properly display the number of unseen messages in an MH mailbox. This patch is against version 0.2.2 of gbuffy. The latest gbuffy is 0.2.3, but no one has ported the unseen patch yet. If you do, please send it to the exmh-workers@redhat.com mailing list. exmh-2.9.0/misc/README.comp.pl0000644000170700017070000000100213201227060015161 0ustar valdisvaldisThis is the start of a script that lets you use netscape's mailto: links with exmh. It could be extended quite a bit, and is pretty rough right now. here is the basic instructions: - install muttzilla, http://www3.telus.net/brian_winters/mutt/ - put comp.pl somewhere in your path, make the changes to the paths at the top of the script - I use the following for my .muttzillarc: mailscript=mzmail.sh mailterm=None mailargs=mutt mailprog=comp.pl Comments and questions: Scott Lipcon, slipcon@mercea.net exmh-2.9.0/misc/RPM/0000755000170700017070000000000013201227060013377 5ustar valdisvaldisexmh-2.9.0/misc/RPM/exmh-2.1.0-conf.patch0000644000170700017070000000603713201227060016746 0ustar valdisvaldis--- exmh-2.1.0/exmh-async.sjl Tue Dec 17 17:37:47 1996 +++ exmh-2.1.0/exmh-async Tue Dec 17 18:01:10 1996 @@ -1,4 +1,4 @@ -#!wish -f +#!/usr/bin/wish -f # # async editor frontend for exmh # Arg1: invoking interpreter's name (from [winfo name .]) *** exmh-2.1.0/exmh Thu Jul 23 19:02:17 1999 --- exmh-2.1.0/exmh~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # TK interface to the MH Mail utility # Brent Welch --- 1,4 ---- ! #!/usr/bin/wish -f # # TK interface to the MH Mail utility # Brent Welch *************** *** 17,22 **** --- 17,49 ---- # The following lines are patched by exmh.install #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version 2.1.0} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/local/faces/faces + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp,path) /usr/bin + set pgp(pgp5,path) /usr/bin + set pgp(gpg,path) /usr/bin + set glimpse(path) /usr/local/bin + set sound(cmd) {/usr/demo/SOUND/play -v 38} + set exmh(library) /usr/lib/exmh-2.1.0 + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-2.1.0 + #END CONFIGURATION if [catch {file join a b}] { child process exited abnormally *** exmh-2.1.0/exmh-bg Thu Jul 22 19:02:17 1999 --- exmh-2.1.0/exmh-bg~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module --- 1,4 ---- ! #!/usr/bin/wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module *************** *** 17,22 **** --- 17,49 ---- #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version 2.1.0} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/local/faces/faces + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp, path) /usr/bin + set pgp(pgp5, path) /usr/bin + set pgp(gpg, path) /usr/bin + set glimpse(path) /usr/local/bin + set sound(cmd) {/usr/demo/SOUND/play -v 38} + set exmh(library) /usr/lib/exmh-2.1.0 + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-2.1.0 + #END CONFIGURATION exmh-2.9.0/misc/RPM/exmh.wmconfig0000644000170700017070000000014513201227060016073 0ustar valdisvaldisexmh name "exmh" exmh description "MH Mail Front End" exmh exec "exmh &" exmh group "Utilities/Mail" exmh-2.9.0/misc/RPM/exmh.desktop0000644000170700017070000000027313201227060015735 0ustar valdisvaldis[Desktop Entry] Name=exmh Name[sv]=exmh Type=Application Comment=Mail reader which handles mh-style mail folders Comment[sv]=E-postläsare som kan hantera e-postmappar av mh-typ Exec=exmh exmh-2.9.0/misc/RPM/exmh-2.1.2-conf.patch0000644000170700017070000000601313201227060016742 0ustar valdisvaldis--- exmh-2.1.0/exmh-async.sjl Tue Dec 17 17:37:47 1996 +++ exmh-2.1.0/exmh-async Tue Dec 17 18:01:10 1996 @@ -1,4 +1,4 @@ -#!wish -f +#!/usr/bin/wish -f # # async editor frontend for exmh # Arg1: invoking interpreter's name (from [winfo name .]) *** exmh-2.1.2/exmh Thu Jul 23 19:02:17 1999 --- exmh-2.1.2/exmh~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # TK interface to the MH Mail utility # Brent Welch --- 1,4 ---- ! #!/usr/bin/wish -f # # TK interface to the MH Mail utility # Brent Welch *************** *** 17,22 **** --- 17,49 ---- # The following lines are patched by exmh.install #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version 2.1.2 06/07/2000} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/lib/faces + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp,path) /usr/bin + set pgp(pgp5,path) /usr/bin + set pgp(gpg,path) /usr/bin + set glimpse(path) /usr/bin + set sound(cmd) {/usr/bin/play -v 38} + set exmh(library) /usr/lib/exmh-2.1.2 + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-2.1.2 + #END CONFIGURATION if [catch {file join a b}] { child process exited abnormally *** exmh-2.1.2/exmh-bg Thu Jul 22 19:02:17 1999 --- exmh-2.1.2/exmh-bg~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module --- 1,4 ---- ! #!/usr/bin/wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module *************** *** 17,22 **** --- 17,49 ---- #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version 2.1.2 (06/07/2000)} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/lib/faces/ + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp,path) /usr/bin + set pgp(pgp5,path) /usr/bin + set pgp(gpg,path) /usr/bin + set glimpse(path) /usr/bin + set sound(cmd) {/usr/bin/play -v 38} + set exmh(library) /usr/lib/exmh-2.1.2 + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-2.1.2 + #END CONFIGURATION exmh-2.9.0/misc/RPM/exmh.spec0000644000170700017070000001207313201227060015217 0ustar valdisvaldisSummary: The exmh mail handling system. Name: exmh Version: EXMHVERSION Release: 1 BuildArchitectures: noarch Requires: mh, metamail Copyright: freeware Group: Applications/Mail Source0: ftp://ftp.tcl.tk/pub/tcl/exmh/exmh-%{version}.tar.gz Url: http://www.beedub.com/exmh/ Source1: exmh.wmconfig Source2: exmh.desktop # The conf patch includes the version number, so it needs to be # updated for every revision even if it applies without being # updated. Use the exmh.install script to make sure that we # keep up with new paths that exmh wants to know about, and # make sure to change all the paths that need to be changed # by comparing to the previous conf patch. Patch0: exmh-%{version}-conf.patch #BuildRoot: %{_tmppath}/%{name}-root Summary(de): EXMH-Mail-Programm Summary(fr): Programme de courrier EXMH Summary(tr): e-posta yazýlýmý Summary(es): Pograma lector de correo exmh %description exmh is a graphical interface to the MH mail system. It includes MIME support, faces, glimpse indexing, color highlighting, PGP interface, and more. Requires sox (or play) for sound support. %description -l es exmh es un interface grafico para el sistema de correo MH. Incluye soporte para tipos MIME, faces, indexacion mediante glimpse, marcado en colores de las cabeceras, PGP y GPGP, enlaces URL, y muchas mas cosas. Necesita sox (o play) para el sonido %description -l de exmh ist eine grafische Oberfläche für das MH-Mail-System. Zu den Funktionen gehören MIME-Unterstützung, Faces, Glimpse-Indexing, farbiges Markieren, PGP-Schnittstelle usw. Erfordert sox (oder play) für Sound-Unterstützung. %description -l fr exmh est uen interface graphique au système de courrier MH. Il gère MIME, les aspects, l'indexation glimpse, la mise en valeur par couleurs, PGP, et autres. Il faut sox (ou play) pour gérér le son. %description -l tr exmh, yaygýn olarak kullanýlan mh paketi için X11 arayüzüdür. MIME desteði, PGP desteði, faces, glimpse yardýmýyla dizin oluþturma gibi yetenekleri vardýr. Ses desteði için sox (ya da play) gerekir. %package misc Summary: exmh misc contributed utils Group: Applications/Mail %description misc The misc package contains user contributed programs which work well with exmh. %prep %setup -q -n exmh-%{PACKAGE_VERSION} for i in *.MASTER; do cp $i ${i%%.MASTER} done %patch0 -p1 -b .conf %build echo 'auto_mkindex ./lib *.tcl' | tclsh %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT/etc/X11/wmconfig mkdir -p $RPM_BUILD_ROOT/etc/X11/applnk/Internet mkdir -p $RPM_BUILD_ROOT{%{_bindir},%{_mandir}/man1} mkdir -p $RPM_BUILD_ROOT%{_libdir}/exmh-%{version} mkdir -p $RPM_BUILD_ROOT%{_libdir}/exmh-%{version}/misc for i in exmh exmh-bg exmh-async ftp.expect inc.expect; do install -m755 $i $RPM_BUILD_ROOT/%{_bindir} done for i in *.l; do install -m644 $i $RPM_BUILD_ROOT%{_mandir}/man1/${i%%.l}.1 done cp -ar lib/* $RPM_BUILD_ROOT/usr/lib/exmh-%{version} cp -ar misc/* $RPM_BUILD_ROOT/usr/lib/exmh-%{version}/misc cp %SOURCE2 $RPM_BUILD_ROOT/etc/X11/applnk/Internet/ install -m644 $RPM_SOURCE_DIR/exmh.wmconfig $RPM_BUILD_ROOT/etc/X11/wmconfig/exmh find $RPM_BUILD_ROOT/usr/lib/exmh-%{version} -type f | grep -v $RPM_BUILD_ROOT/usr/lib/exmh-%{version}/misc |sed -e "s|$RPM_BUILD_ROOT||" > filelist cat filelist %clean rm -rf $RPM_BUILD_ROOT # # Maybe the /usr/lib stuff in the %dir clause and the find statement should # be changed to use %{_libdir}? Does %files -f support macros? # %files -f filelist %defattr(-,root,root) %dir /usr/lib/exmh-%{version} %dir /usr/lib/exmh-%{version}/html %dir /usr/lib/exmh-%{version}/bitmaps %doc COPYRIGHT exmh.BUGS exmh.CHANGES exmh.TODO exmh.README lib/html/ %config /etc/X11/wmconfig/exmh %config /etc/X11/applnk/Internet/exmh.desktop %{_bindir}/exmh %{_bindir}/exmh-bg %{_bindir}/exmh-async %{_bindir}/ftp.expect %{_bindir}/inc.expect #%{_libdir}/exmh-%{version} %{_mandir}/man1/exmh.1* %files misc %defattr(-,root,root) %{_libdir}/exmh-%{version}/misc %changelog * Sun Jul 29 2001 Anders Eriksson - Made the root package exclude the misc/ directory * Thu May 24 2001 Scott Lipcon - change rpm to build exmh-misc package as well. * Sat Oct 14 2000 Scott Lipcon - changes to support RPM4, bring specfile in line with Redhat's, hopefully * Sun Aug 20 2000 Scott Lipcon - overdue 2.2 patch, fixes pgp6 * Wed Jun 07 2000 Scott Lipcon - update for exmh 2.1.2, coming soon. * Fri Sep 17 1999 Scott Lipcon - Added Spanish translation, courtesy of Francisco Monserrat * Thu Jul 29 1999 Scott Lipcon - update to exmh 2.1.0, add spec file to distribution, and added a 'rpm' target to the Makefile * Tue Mar 03 1999 Scott Lipcon - update to exmh 2.0.3 * Sat Aug 15 1998 Jeff Johnson - build root * Fri Apr 24 1998 Prospector System - translations modified for de, fr, tr * Fri Apr 10 1998 Donnie Barnes - updated to 2.0.2 * Wed Oct 22 1997 Donnie Barnes - added wmconfig support exmh-2.9.0/misc/RPM/exmh-conf.patch0000644000170700017070000000613213201227060016306 0ustar valdisvaldis--- exmh-VERSION/exmh-async.sjl Tue Dec 17 17:37:47 1996 +++ exmh-VERSION/exmh-async Tue Dec 17 18:01:10 1996 @@ -1,4 +1,4 @@ -#!wish -f +#!/usr/bin/wish -f # # async editor frontend for exmh # Arg1: invoking interpreter's name (from [winfo name .]) *** exmh-VERSION/exmh Thu Jul 23 19:02:17 1999 --- exmh-VERSION/exmh~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # TK interface to the MH Mail utility # Brent Welch --- 1,4 ---- ! #!/usr/bin/wish -f # # TK interface to the MH Mail utility # Brent Welch *************** *** 17,22 **** --- 17,50 ---- # The following lines are patched by exmh.install #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version VERSION RELDATE} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/lib/faces + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp,path) /usr/bin + set pgp(pgp5,path) /usr/bin + set pgp(gpg,path) /usr/bin + set pgp(pgp6,path) /usr/bin + set glimpse(path) /usr/bin + set sound(cmd) {/usr/bin/play -v 38} + set exmh(library) /usr/lib/exmh-VERSION + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-VERSION + #END CONFIGURATION if [catch {file join a b}] { child process exited abnormally *** exmh-VERSION/exmh-bg Thu Jul 22 19:02:17 1999 --- exmh-VERSION/exmh-bg~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module --- 1,4 ---- ! #!/usr/bin/wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module *************** *** 17,22 **** --- 17,50 ---- #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version VERSION (RELDATE)} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/lib/faces/ + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp,path) /usr/bin + set pgp(pgp5,path) /usr/bin + set pgp(gpg,path) /usr/bin + set pgp(pgp6,path) /usr/bin + set glimpse(path) /usr/bin + set sound(cmd) {/usr/bin/play -v 38} + set exmh(library) /usr/lib/exmh-VERSION + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-VERSION + #END CONFIGURATION exmh-2.9.0/misc/RPM/exmh-2.2-conf.patch0000644000170700017070000000605713201227060016613 0ustar valdisvaldis--- exmh-2.2/exmh-async.sjl Tue Dec 17 17:37:47 1996 +++ exmh-2.2/exmh-async Tue Dec 17 18:01:10 1996 @@ -1,4 +1,4 @@ -#!wish -f +#!/usr/bin/wish -f # # async editor frontend for exmh # Arg1: invoking interpreter's name (from [winfo name .]) *** exmh-2.2/exmh Thu Jul 23 19:02:17 1999 --- exmh-2.2/exmh~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # TK interface to the MH Mail utility # Brent Welch --- 1,4 ---- ! #!/usr/bin/wish -f # # TK interface to the MH Mail utility # Brent Welch *************** *** 17,22 **** --- 17,49 ---- # The following lines are patched by exmh.install #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version 2.2 06/23/2000} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/lib/faces + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp,path) /usr/bin + set pgp(pgp5,path) /usr/bin + set pgp(gpg,path) /usr/bin + set pgp(pgp6,path) /usr/bin + set glimpse(path) /usr/bin + set sound(cmd) {/usr/bin/play -v 38} + set exmh(library) /usr/lib/exmh-2.2 + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-2.2 + #END CONFIGURATION if [catch {file join a b}] { child process exited abnormally *** exmh-2.2/exmh-bg Thu Jul 22 19:02:17 1999 --- exmh-2.2/exmh-bg~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module --- 1,4 ---- ! #!/usr/bin/wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module *************** *** 17,22 **** --- 17,49 ---- #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version 2.2 (06/23/2000)} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/lib/faces/ + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp,path) /usr/bin + set pgp(pgp5,path) /usr/bin + set pgp(gpg,path) /usr/bin + set pgp(pgp6,path) /usr/bin + set glimpse(path) /usr/bin + set sound(cmd) {/usr/bin/play -v 38} + set exmh(library) /usr/lib/exmh-2.2 + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-2.2 + #END CONFIGURATION exmh-2.9.0/misc/RPM/exmh-2.1.1-conf.patch0000644000170700017070000000600613201227060016743 0ustar valdisvaldis--- exmh-2.1.0/exmh-async.sjl Tue Dec 17 17:37:47 1996 +++ exmh-2.1.0/exmh-async Tue Dec 17 18:01:10 1996 @@ -1,4 +1,4 @@ -#!wish -f +#!/usr/bin/wish -f # # async editor frontend for exmh # Arg1: invoking interpreter's name (from [winfo name .]) *** exmh-2.1.0/exmh Thu Jul 23 19:02:17 1999 --- exmh-2.1.0/exmh~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # TK interface to the MH Mail utility # Brent Welch --- 1,4 ---- ! #!/usr/bin/wish -f # # TK interface to the MH Mail utility # Brent Welch *************** *** 17,22 **** --- 17,49 ---- # The following lines are patched by exmh.install #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version 2.1.1 (devel)} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/lib/faces + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp,path) /usr/bin + set pgp(pgp5,path) /usr/bin + set pgp(gpg,path) /usr/bin + set glimpse(path) /usr/bin + set sound(cmd) {/usr/bin/play -v 38} + set exmh(library) /usr/lib/exmh-2.1.1 + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-2.1.1 + #END CONFIGURATION if [catch {file join a b}] { child process exited abnormally *** exmh-2.1.0/exmh-bg Thu Jul 22 19:02:17 1999 --- exmh-2.1.0/exmh-bg~ Thu Jul 29 21:31:11 1999 *************** *** 1,4 **** ! #!wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module --- 1,4 ---- ! #!/usr/bin/wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module *************** *** 17,22 **** --- 17,49 ---- #CONFIGURATION + set wish /usr/bin/wish + set exmh(version) {version 2.1.1 (devel)} + set exmh(name) exmh + set exmh(maintainer) welch@acm.org + set mh_path /usr/bin + set exmh(slocal) /usr/lib/nmh/slocal + set mime(dir) /usr/bin + set mailcap_default /etc/mailcap + set mimetypes_default /etc/mime.types + set exmh(expect) /usr/bin/expect + set exmh(expectk) /usr/bin/expectk + set faces(dir) /usr/lib/faces/ + set faces(set,user) {local users usenix misc} + set faces(set,unknown) {domains unknown} + set faces(set,news) news + set faces(defaultDomain) eng.sun.com + set faces(suffix) {xpm gif xbm} + set pgp(pgp, path) /usr/bin + set pgp(pgp5, path) /usr/bin + set pgp(gpg, path) /usr/bin + set glimpse(path) /usr/bin + set sound(cmd) {/usr/bin/play -v 38} + set exmh(library) /usr/lib/exmh-2.1.1 + set install(dir,bin) /usr/bin + set install(dir,man) /usr/man/manl + set install(dir,lib) /usr/lib/exmh-2.1.1 + #END CONFIGURATION exmh-2.9.0/misc/RPM/exmh-2.0.3-conf.patch0000644000170700017070000000522513201227060016746 0ustar valdisvaldis--- exmh-2.0alpha/exmh-async.marc Tue Dec 17 17:37:47 1996 +++ exmh-2.0alpha/exmh-async Tue Dec 17 18:01:10 1996 @@ -1,4 +1,4 @@ -#!wish -f +#!/usr/bin/wish -f # # async editor frontend for exmh # Arg1: invoking interpreter's name (from [winfo name .]) --- exmh-2.0alpha/exmh-bg.marc Tue Dec 17 17:38:05 1996 +++ exmh-2.0alpha/exmh-bg Tue Dec 17 18:01:09 1996 @@ -1,4 +1,4 @@ -#!wish -f +#!/usr/bin/wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module @@ -16,6 +16,29 @@ # any specification. #CONFIGURATION +set wish /usr/bin/wish +set exmh(version) {version 2.1.0} +set exmh(name) exmh +set exmh(maintainer) welch@acm.org +set mh_path /usr/bin/mh +set exmh(slocal) /usr/lib/mh/slocal +set mime(dir) /usr/bin +set mailcap_default /etc/mailcap +set exmh(expect) /usr/bin/expect +set exmh(expectk) /usr/bin/expectk +set faces(dir) /usr/local/faces/faces +set faces(set,user) {local users usenix misc} +set faces(set,unknown) {domains unknown} +set faces(defaultDomain) eng.sun.com +set faces(suffix) {xpm gif xbm} +set pgp(path) /usr/bin +set glimpse(path) /usr/bin +set sound(cmd) {/usr/demo/SOUND/play -v 38} +set exmh(library) /usr/lib/exmh-2.1.0 +set install(dir,bin) /usr/bin +set install(dir,man) /usr/man/man1 +set install(dir,lib) /usr/lib/exmh-2.1.0 + #END CONFIGURATION wm withdraw . --- exmh-2.0alpha/exmh.marc Tue Dec 17 17:39:05 1996 +++ exmh-2.0alpha/exmh Tue Dec 17 18:01:09 1996 @@ -1,4 +1,4 @@ -#!wish -f +#!/usr/bin/wish -f # # TK interface to the MH Mail utility # Brent Welch @@ -16,6 +16,29 @@ # The following lines are patched by exmh.install #CONFIGURATION +set wish /usr/bin/wish +set exmh(version) {version 2.1.0} +set exmh(name) exmh +set exmh(maintainer) welch@acm.org +set mh_path /usr/bin/mh +set exmh(slocal) /usr/lib/mh/slocal +set mime(dir) /usr/bin +set mailcap_default /etc/mailcap +set exmh(expect) /usr/bin/expect +set exmh(expectk) /usr/bin/expectk +set faces(dir) /usr/local/faces/faces +set faces(set,user) {local users usenix misc} +set faces(set,unknown) {domains unknown} +set faces(defaultDomain) eng.sun.com +set faces(suffix) {xpm gif xbm} +set pgp(path) /usr/bin +set glimpse(path) /usr/bin +set sound(cmd) {/usr/demo/SOUND/play -v 38} +set exmh(library) /usr/lib/exmh-2.0.3 +set install(dir,bin) /usr/bin +set install(dir,man) /usr/man/man1 +set install(dir,lib) /usr/lib/exmh-2.1.0 + #END CONFIGURATION if {$tk_version < 4.1} { --- exmh-2.0alpha/ftp.expect.marc Tue Dec 17 17:40:55 1996 +++ exmh-2.0alpha/ftp.expect Tue Dec 17 18:01:10 1996 @@ -1,4 +1,4 @@ -#!expect -f +#!/usr/bin/expect -f set site [lindex $argv 0] set dir [lindex $argv 1] exmh-2.9.0/misc/README.lockedrcvstore0000644000170700017070000000167013201227060016655 0ustar valdisvaldis README.lockedrcvstore Put file locking around rcvstore Purpose of Hack --------------- This isn't truly an exmh hack, but it's more of an MH/nmh hack. Under qmail, it's more likely than under sendmail that more than one email message will arrive at the same time. This adds file locking to exmh. What You'll Need ---------------- I use it with qmail. I haven't thought about how to make it work with sendmail. It also calls 'lockfile' which comes with procmail. Instructions ------------ Instead of calling rcvstore in your .qmail files, simply call lockedrcvstore. lockedrcvstore provides the '+', so you'll need to remove that from your rcvstore call. For example, .qmail-important might look something like this: |lockedrcvstore ImportantStuff any additional arguments are also passed, so you can flag a sequence like this: |lockedrcvstore ImportantStuff -sequence urgent Author ------ Chris Garrigues exmh-2.9.0/misc/README.mhthread0000644000170700017070000000172713201227060015423 0ustar valdisvaldismhthread -- sort an MH folder into 'threaded' order This will thread an MH folder. It re-orders the messages (as sortm(1) would do), and annotates each one with a new header, "X-MH-Thread-Markup", which can be displayed by scan(1). Together, this results in the messages being displayed in "threaded" order, as in trn(1) or mutt(1). Sequences will be rewritten appropriately. The folder will also be "packed", as if 'folder - pack' had been run; see folder(1). RESULTS Here's some sample output from scan(1), after threading the folder: 430 03/23 mathew 3 [Asrg] Re: [OffTopic - NNTP] 431 03/23 Kee Hinckley 5 |- [Asrg] Re: [OffTopic - NNTP] 432 -03/23 Chuq Von Rospach 11 | |- Parameters for success? (was Re: [A 433 03/23 To:Chuq Von Rospa 4 | | \- Re: Parameters for success? (was 434 03/23 Matt Sergeant 3 | \- Re: [Asrg] Re: [OffTopic - NNTP] 435 03/23 Chuq Von Rospach 7 \- Re: [Asrg] Re: [OffTopic - NNTP] exmh-2.9.0/misc/README.bifffolder0000644000170700017070000000147213201227060015726 0ustar valdisvaldis README.bifffolder Script to cause exmh to recognise that new mail has arrived. Purpose of Hack --------------- When new mail arrives, look to see if there's a running instance of exmh and if there is, tell it to rescan a mailbox What You'll Need ---------------- I use it with qmail. I haven't thought about how to make it work with sendmail. Also, requires that the exmhwrapper be in use. Instructions ------------ Add an additional line to any .qmail file right after the rcvstore which pipes the message to this script. The script takes a single argument which is the name of the folder which the mail was delivered to. For example, .qmail-important might look something like this: |lockedrcvstore ImportantStuff |bifffolder ImportantStuff Author ------ Chris Garrigues exmh-2.9.0/misc/README.compface0000644000170700017070000000237313201227060015402 0ustar valdisvaldisThe compface.patch file has a patch that teaches the compface and uncompface programs how to read .xbm format (X bitmap) files, instead of the arcane .ikon files it used before. This patch should apply OK to the files in the compface directory of the picons (a.k.a. facesaver) software. With the new version of uncompface, the exmh X-Face pipeline can just be: uncompface -X To create the X-Face header from a 48x48 .xbm file, just do compface your.xbm > out The file "out" will contain three lines of jibberish. You need to add the X-Face: header e.g. out contains: znu_@QbSegynS/\2YND%-w_L.V$bG-M.}<:^^3tS,BszwEdNEo)-/"eZF^+1]M%>A#"QV8U #*cFsKsnwC63B`A#"QV8U #*cFsKsnwC63B`A#"QV8U #*cFsKsnwC63B` Purpose of Hack --------------- Allows you to filter a region of text, in your sedit window, through the "par" formatter for beautification. What You'll Need ---------------- You need a copy of "par", which is available from its authors web site at http://www.cs.berkeley.edu/~amc/Par/. Instructions ------------ In your file of exmh hacks[1] (which should reside in the directory named in Preferences->Hacking Support->User Library Directory), add the following. proc jk-format {t} { global sedit # the stuff after "-r" is options to "par"; change at will set res [exec par -w$sedit(lineLength) -rTbgqR -B=.\?_A_a -Q=_s\>\| \ << [selection get]] if {![catch "set tndx [$t index sel.first]"]} { $t delete sel.first sel.last } else { set tndx [$t index insert] } $t mark set insert $tndx $t insert insert $res } proc Hook_SeditInitFormat {d t} { bind $t "jk-format $t" } [1] This file can be called "user.tcl" (or whatever.tcl, really). If you don't have one already, copy "user.tcl" from the exmh library directory and use it as a template for your own. After you do this, run a "tclsh" in this same directory. From it, do "auto_mkindex . *.tcl" to update your "tclIndex", then restart exmh. Usage ----- After you've restarted exmh, you can use the new binding for Meta-q (note that on a Sun keyboard, this "Meta" is actually the small, black "diamond" key next to the space bar; it is on my system, anyway). In particular, you can select a region of text (in your sedit window), then hit Meta-q to send it through "par" and have the result put back into your sedit window, in place of the original text. To Do ----- Some kind of an "undo" facility would be nice... Author ------ John Klassa exmh-2.9.0/misc/README.cite0000644000170700017070000001204313201227060014544 0ustar valdisvaldis README.cite Instructions for Adding a Supercite-like Quoter to Sedit Time-stamp: <1999-05-07 13:07:33 klassa> Purpose of Hack --------------- Allows you to quote a message, in a reply, in the spirit of Emacs' supercite utility. Example: --snip-- >>>>> On Thu, 6 May 1999, "Hal" == Hal DeVore wrote: Hal> *) cite Perl script and info on using it Hal> *) John Klassa's cite-lookup and cite-update and procs and Hal> doc to use 'em I, unfortunately, have been messing around with these and don't think I have a "good" copy of any one of them any longer. If somebody can come up with good versions, I can try to write up some instructions to go with 'em. --snip-- This hack adds the ">>>>> On Thu..." and "Hal>" text for you. You can also specify arbitrary attributions for particular email addresses, which are stored persistently in DBM a file. What You'll Need ---------------- You need perl (which is available from http://www.perl.com, built with DBM support if you intend to use the arbitrary, persistent attribution mechanism) as well as the "cite", "cite-lookup" and "cite-update" scripts. You'll also need "par", a C program which does advanced text formatting and is available from http://www.cs.berkeley.edu/~amc/Par. Instructions ------------ Put the "cite", "cite-lookup" and "cite-update" scripts somewhere in your path, so that exmh will find them when it attempts to execute them. Likewise, build "par" and put the executable somewhere in your path. In your file of exmh hacks[1] (which should reside in the directory named in Preferences->Hacking Support->User Library Directory), add the following. proc jk-cite {m t} { global sedit set res [exec cite -w$sedit(lineLength) $m [glob ~/@]] $t insert end "$res" } proc jk-attr-update {t c} { catch { exec cite-update << $c } res if {$res != ""} { tk_dialog .citeoops "Cite Update: Oops!" $res error 0 "Ack!" } } proc jk-add-attr {t} { set w [winfo parent [winfo parent $t]] if {![winfo exists $w.jka]} { pack [frame $w.jka] -side top -fill x -ipady 2 } if {![winfo exists $w.jka.l]} { pack [label $w.jka.l -text "Cite Update"] -side left } if {![winfo exists $w.jka.e]} { pack [entry $w.jka.e] -side left -expand yes -fill x -ipady 2 } if {![winfo exists $w.jka.b]} { pack [button $w.jka.b -text Update \ -command "jk-attr-update $t \[$w.jka.e get\]"] \ -side left -ipady 2 } $w.jka.e delete 0 end $w.jka.e insert end [exec cite-lookup $::address] } proc Hook_SeditInitCite {d t} { bind $t "jk-cite -f $t" bind $t "jk-cite -nf $t" jk-add-attr $t } [1] This file can be called "user.tcl" (or whatever.tcl, really). If you don't have one already, copy "user.tcl" from the exmh library directory and use it as a template for your own. Also, make sure that Preferences->Quoting->Enable Quoting is turned on, so that the message you're replying to, when you reply, is available by the name "~/@" (the "jk-cite" procedure looks for it there; the "To Do" section, below, touches on this). After you do this, run a "tclsh" in this same directory. From it, do "auto_mkindex . *.tcl" to update your "tclIndex", then restart exmh. Usage ----- After you've restarted exmh, you can use the new bindings for Meta-c and Meta-C (note that on a Sun keyboard, this "Meta" is actually the small, black "diamond" key next to the space bar; it is on my system, anyway). In particular, once you have exmh bring up a "reply" window, you can hit Meta-c to have the original message (now nicely quoted and formatted) inserted at the end of your sedit buffer. If you use Meta-C (capital C) instead, you get the same result but without formatting (which is handy when the original contains text that you don't want to have wrapped, for example). You should also see a new region at the bottom of your sedit window, with a label that reads "Cite Update". When you reply to a message, the address to which you're replying will appear in this region's entry widget. If you put arbitrary attribution text after the equals sign, then hit the "Update" button, your attribution text will be permanently stored for the indicated address, and will be used whenever that address is encountered by cite. For example, if you replying to "John Doe ", the "Cite Update" box will contain: john.doe@nowhere.com= If you put in "Uncle John", as in: john.doe@nowhere.com=Uncle John hit "Update" and *then* hit Meta-c to bring in the original message's text, you should see something like: >>>>> On Thu, 6 May 1999, "Uncle John" == John Doe wrote: Uncle John> Hello, nephew! Uncle John> Hope you've been well... To Do ----- Some kind of an "undo" facility would be nice... Also, using the preference setting in lieu of the hard-coded filename "~/@" would be nice. Author ------ John Klassa exmh-2.9.0/misc/cite0000755000170700017070000002511113201227060013613 0ustar valdisvaldis#!/usr/bin/perl -w # # If you are running perl version 4, please run: # # & perl -p -i -e 's|chomp\;|s/\\n\$//\;|g; s/my\(/local\(/g;' cite # ########################################################################### # @(#)cite 1.12 10/21/97 # @(#) 97/06/05 klassa@ivc.com, klassa@ipass.net (John Klassa) # @(#) 97/10/01 steven@dante.org.uk (Steven Bakker) # @(#) 97/10/16 henrik@itb.biologie.hu-berlin.de (Henrik Seidel) # # cite -- A minimal "supercite.el" workalike. # # This is icky, icky code. If some clueful person would care to # clean it up, I'd be most grateful! :-) # ########################################################################### my($format, $attribution, $count, $arg, $date, $from, @files, $attr, $fmt, $curr, $tmp, $tmp1, $tmp2, @tmp, $out, $use_raw, $erase, $spcidx, @sline, $thisline, $linewidth, $tlw, %attribution_headers); $0 =~ s|.*/||g; $USAGE =< in the while loop (below) does the right # thing & doesn't attempt to process files named after our command line # switches. :-) # @ARGV = @files; # # Grab information out of the header. # # Initialise date. $date = localtime(time); # Some Perl versions (such as the 4.036 I'm running) don't do # localtime in the scalar version... chop($date = `date`) unless defined($date); while (<>) { chomp; # # If we've hit the header/body separator, bail. # last if /^\s*$/; # # If we've got the "From" line, extract the relevant parts. # if (/^from:/i) { ($from, $attr) = &munge($_); $attribution = $attr unless $attribution; } # # Pick out the date, if on the "Date" line. # $date = $1 if /^date:\s*(.*\S)/i; } # # Get rid of the time at the end of the date, and replace days of the form # 01,02,03,... with the single-digit form. # $date =~ s/ [0-9:]*( ([\+-][0-9]*|[A-Z]*))?( \(.*\))?$//; $date =~ s/\b0([0-9])\b/$1/; # # Grab the body & do the attribution... Work into a temporary variable # so that we can check return value from the use of "par" (and take # appropriate counter measures, if necessary), easily. # $ATTR_HDR_PREFIX = ">>>>>"; #$ATTR_HDR_PREFIX = "==>"; $attribution_headers{"$attribution==$from"} = 1; $out = "\n$ATTR_HDR_PREFIX On $date," . "\n$ATTR_HDR_PREFIX \"$attribution\" == $from wrote:\n" ; undef $curr; while (<>) { # # If this is a previous "attribution header", write it out as is: # # "Canonicalise" some well-known attribution header prefixes: s/^>>>>>/$ATTR_HDR_PREFIX/g; s/^==>/$ATTR_HDR_PREFIX/g; chomp; if (/^$ATTR_HDR_PREFIX/) { if (/^$ATTR_HDR_PREFIX\s*On[^"]*"(\S+)"\s*==\s*(.*\S)\s*wrote:\s*$/) { my $attr = "$1==$2"; next if defined($attribution_headers{$attr}); $attribution_headers{$attr} = 1; } if ((!defined($curr) || $curr ne $ATTR_HDR_PREFIX) && !$count) { $curr = $ATTR_HDR_PREFIX; $out .= "\n"; # don't increment $count } $out .= $_."\n\n"; # Make sure there's an always an extra empty # line! $count++; next; } # # If the line contains a >, assume it's from a previous attribution. # Attempt to extract the relevant portion. For example, in a line # like "Bob> Tom> okay, go ahead", we want the attribution to be # "Tom" and the text to be attributed to be "okay, go ahead" (i.e. # the "Bob" part is irrelevant, since Bob was just quoting Tom; what # we want to keep is the notion that Tom said something)... # $tmp = ''; if (/^\s*[A-Z\d\+]*>/i) { /^\s*(([A-Z\d\+]*>)*\s*)([A-Z\d\+]*>)(.*)$/i; ($tmp1, $tmp2, $_) = ($1, $3, $4); # # If the attribution is blank, use a '+'. # if ("$tmp2" eq ">") { $tmp = '+'; $tmp .= $tmp1 . " " unless "$tmp1" eq ""; $tmp =~ s/>>/> >/g; $tmp =~ s/ / /g; } else { ($tmp) = $tmp2 =~ /(.+)>/; } # # To make the -w and 'use strict' happy, make sure $_ has a # value in the event that the earlier split caused it to become # undefined. # $_ = '' unless defined($_); } # # Clean up the line by removing leading/trailing space. # s/^\s+|\s+$//g; # # If the attribution has changed or there's a blank line in the # text, and we haven't emitted a blank line already, do so. The # intent is to separate logical portions of the message without # allowing double (or greater) spacing. # $out .= "\n" if ((!defined($curr) || $tmp ne $curr || $_ eq '') && !$count++); # # If the line isn't empty, spit it out. We make sure that there aren't # any lines with words too long for par to handle (by splitting them -- # no, it's not nice). # @sline = (); $tlw = $linewidth - (length(($tmp) ? $tmp : $attribution) + 4); while ($format && $tlw>0 && (length > $tlw)) { $count = 0; $spcidx = &max(rindex($_, " ", $tlw-1), rindex($_, "\t", $tlw-1), rindex($_, "-", $tlw-1)); if ($spcidx < 0) { $spcidx = $tlw-1; } push(@sline, substr($_, 0, $spcidx+1)); $sline[$#sline] =~ s/\s+$//g; $_ = substr($_, $spcidx+1); s/^\s+//g; } if ($_ ne '') { $count = 0; push(@sline, $_); } foreach $thisline (@sline) { $out .= sprintf(" %s> %s\n", ($tmp) ? $tmp : $attribution, $thisline); } # # Remember the attribution, so that we've got something to compare # against on the next pass. # $curr = $tmp; } # # Do the actual output... If formatting is desired, use par. If not, # or if par fails, just emit the text as it is. # $use_raw = 1; $erase = 0; $SIG{'PIPE'} = 'IGNORE'; if ($format) { open(PAR, "| $fmt > /tmp/$$"); # failure case checked later... print PAR $out; close(PAR); $erase = 1; unless ($?) { if (open(INP, "/tmp/$$")) { print (); close(INP); $use_raw = 0; } } } print $out if $use_raw; unlink "/tmp/$$" if ($erase && -e "/tmp/$$"); ########################################################################### # max - returns the greatest of its args ########################################################################### sub max { my(@sorted) = sort compare @_; shift @sorted; } ########################################################################### # compare - subroutine for the sort command above ########################################################################### sub compare { $b <=> $a; } ########################################################################### # munge -- Rip out the good stuff & format the result. ########################################################################### sub munge { my($line) = @_; my($attr, $addr, $name); $line =~ s/^from:\s*//i; $name = ''; $addr = $line; if ($line =~ /]+)>/); ($name = $line) =~ s/<[^>]+>//; } elsif ($line =~ /\(/) { ($name) = ($line =~ /\(([^\)]+)\)/); ($addr = $line) =~ s/\([^\)]+\)//; } $addr =~ s/^\s+|\s+$//g; $addr =~ s/[\(\)<>"]//g; $name =~ s/^\s+|\s+$//g; $name =~ s/[\(\)<>"]//g; ($attr = $name || $addr) =~ s/@.*//; if ($attr =~ /^(\S+), (\S+)/) { $attr = $2; } else { $attr =~ s/(\S+).*/$1/; } $attr =~ s/[^\w]//g; $attr =~ s/\s+//g; $name =~ s/^\s+|\s+$//g; $name = length($name) ? $name : $addr; # See if some other attribution is desired... Hashes tied to dbm # files don't seem to support the exists method, so I create a # temporary hash that isn't tied and use it for the initial lookup. # I guess a "defined" check on what's in the tied hash would have # worked, but that may auto-vivify they key I'm looking up... I # suppose I could check it out, easily enough, but I'm too lazy at # the moment. my %lut; dbmopen %lut, "$ENV{HOME}/.cite-lut", 0600; my %local_lut = map { $_ => 1 } keys %lut; my @result; if (exists $local_lut{$addr}) { @result = ($name, $lut{$addr}); } else { @result = ($name, $attr); } dbmclose %lut; return @result; } exmh-2.9.0/misc/comp.pl0000755000170700017070000000437013201227060014243 0ustar valdisvaldis#!/usr/bin/perl -w # Arguments to the script: # 1 to # 2 -c cc # 3 -b bcc # 4 -s subject # 5 -i body file # 6 org use FileHandle; use strict; use Getopt::Long; # set this to your normal components file my $comps = "/home/slipcon/Mail/components"; # I have two variables here because I run netscape and exmh on different # machines. If you run them on the same machine, you can set $usecomps to # the same value as $newcomps. my $newcomps = "/net/mercea/tmp/components.$<.$$"; my $usecomps = "/tmp/components.$<.$$"; #my $usecomps = $newcomps; use vars qw($to $cc $bcc $subj $bodyfile $org); use vars qw($haveto $havecc $havebcc $havesubj $havebodyf $haveorg); $haveto = $havecc = $havebcc = $havesubj = $havebodyf = $haveorg = 1; $to = shift @ARGV; GetOptions("c=s" => \$cc, "b=s" => \$bcc, "s=s" => \$subj, "i=s" => \$bodyfile); $org = shift @ARGV; if (!defined($to)) { $haveto = 0; $to = ""; } if (!defined($cc)) { $havecc = 0; $cc = ""; } if (!defined($bcc)) { $havebcc = 0; $bcc = ""; } if (!defined($subj)) { $havesubj = 0; $subj = ""; } if (!defined($bodyfile)) { $havebodyf = 0; $bodyfile = ""; } if (!defined($org)) { $haveorg = 0; $org = ""; } my $infh = new FileHandle; my $outfh = new FileHandle; $outfh->open(">$newcomps"); $infh->open($comps); while (<$infh>) { chomp; if (/^To:/) { print $outfh $_ . " " . $to . "\n"; $haveto = 0; } elsif ((/^Cc:/) || (/^cc:/)) { print $outfh $_ . " " . $cc . "\n"; $havecc = 0; } elsif ((/^Bcc:/) || (/^bcc:/)) { print $outfh $_ . " " . $bcc . "\n"; $havebcc = 0; } elsif (/^Organization:/) { print $outfh $_ . " " . $org . "\n"; $haveorg = 0; } elsif (/^Subject:/) { print $outfh $_ . " " . $subj . "\n"; $havesubj = 0; } elsif (/^--------/) { # end of components file if ($havebcc) { print $outfh "Bcc: $bcc\n"; $havebcc = 0; } if ($haveorg) { print $outfh "Organization: $org\n"; $haveorg = 0; } print $outfh "--------\n"; if ($havebodyf) { my $bodyfh = new FileHandle; $bodyfh->open($bodyfile); while (<$bodyfh>) { print $outfh $_; } $bodyfh->close(); } } else { print $outfh $_ . "\n"; } } $infh->close(); $outfh->close(); system("echo \"send exmh Msg_Compose -form $usecomps\nexit\n\" | wish"); system("rm $newcomps"); exmh-2.9.0/misc/cite-lookup0000755000170700017070000000117113201227060015122 0ustar valdisvaldis#!/usr/bin/perl -w ########################################################################## # cite-lookup / v0.1 # # Do a look-up in the dbm file(s) that map email addresses to attribution # strings. # # John Klassa / March, 1999 ########################################################################## use strict; my %db; dbmopen %db, "$ENV{HOME}/.cite-lut", 0600 or die "Couldn't tie to '$ENV{HOME}/.cite-lut': $!"; my $did_output; for my $addr (@ARGV) { if (defined $db{$addr}) { print "$addr=$db{$addr}\n"; } else { print "$addr=\n"; } ++$did_output; } print "=\n" unless $did_output; exmh-2.9.0/misc/bifffolder0000755000170700017070000000050113201227060014765 0ustar valdisvaldis#!/bin/sh # # If exmh is running, make it do an flist. # FOLDER=$1 FILE=$HOME/.exmh/.display if [ -f $FILE ]; then DISPLAY=`cat $FILE` if [ "$DISPLAY" != "" ]; then echo "exmh is running" /usr/local/bin/wish -f -display $DISPLAY < + #endif void BigRead(fbuf) *************** *** 70,77 **** --- 73,111 ---- { register int c, i; register char *s, *t; + static char table_inv[] = { 0,8,4,12,2,10,6,14,1,9, 5,13, 3,11, 7,15 }; + static char table_nop[] = { 0,1,2, 3,4, 5,6, 7,8,9,10,11,12,13,14,15 }; + char *table = table_nop; /* optionally invert bits in nibble */ + register inc = 0; /* optionally swap nimmles */ + int bits; t = s = fbuf; + + /* Does this look like an X bitmap ? */ + if (sscanf(s, "#define %*s %d", &bits) == 1) { + if (bits == 48) { + char type1[128]; + char type2[128]; + while (*s && *s++ != '\n'); + if (sscanf(s, "#define %*s %d", &bits) == 1) if (bits == 48) { + while (*s && *s++ != '\n'); + if (sscanf(s, "static %s %s", type1,type2)==2 && + (!strcmp(type1, "char") || + !strcmp(type2, "char"))) { + while (*s && *s++ != '\n'); + inc = 1; + table = table_inv; + } + else fprintf(stderr, + "warning: xbitmap line 3 not static [unsigned] short ...\n"); + } + else fprintf(stderr, "warning: xbitmaps must be 48x48\n"); + } + else fprintf(stderr, "warning: xbitmaps must be 48x48\n"); + } + /* Ensure s is reset if it was not an X bitmap ... */ + if (! inc) s = fbuf; + for(i = strlen(s); i > 0; i--) { c = (int)*(s++); *************** *** 82,88 **** status = ERR_EXCESS; break; } ! *(t++) = c - '0'; } else if ((c >= 'A') && (c <= 'F')) { --- 116,122 ---- status = ERR_EXCESS; break; } ! (t++)[inc] = table[c - '0']; inc = - inc; } else if ((c >= 'A') && (c <= 'F')) { *************** *** 91,97 **** status = ERR_EXCESS; break; } ! *(t++) = c - 'A' + 10; } else if ((c >= 'a') && (c <= 'f')) { --- 125,131 ---- status = ERR_EXCESS; break; } ! (t++)[inc] = table[c - 'A' + 10]; inc = - inc; } else if ((c >= 'a') && (c <= 'f')) { *************** *** 100,109 **** status = ERR_EXCESS; break; } ! *(t++) = c - 'a' + 10; } ! else if (((c == 'x') || (c == 'X')) && (t > fbuf) && (*(t-1) == 0)) ! t--; } if (t < fbuf + DIGITS) longjmp(comp_env, ERR_INSUFF); --- 134,143 ---- status = ERR_EXCESS; break; } ! (t++)[inc] = table[c - 'a' + 10]; inc = - inc; } ! else if (((c == 'x') || (c == 'X')) && (t > fbuf) && ! ((t-1)[-inc] == table[0])) { t--; inc = -inc; } } if (t < fbuf + DIGITS) longjmp(comp_env, ERR_INSUFF); *************** *** 127,136 **** --- 161,179 ---- { register char *s, *t; register int i, bits, digits, words; + extern int xbitmap; + int digsperword = DIGSPERWORD; + int wordsperline = WORDSPERLINE; s = F; t = fbuf; bits = digits = words = i = 0; + if (xbitmap) { + sprintf(t,"#define noname_width 48\n#define noname_height 48\nstatic char noname_bits[] = {\n "); + while (*t) t++; + digsperword = 2; + wordsperline = 15; + } while (s < F + PIXELS) { if ((bits == 0) && (digits == 0)) *************** *** 138,162 **** *(t++) = '0'; *(t++) = 'x'; } ! if (*(s++)) ! i = i * 2 + 1; ! else ! i *= 2; if (++bits == BITSPERDIG) { ! *(t++) = *(i + HexDigits); bits = i = 0; ! if (++digits == DIGSPERWORD) { *(t++) = ','; digits = 0; ! if (++words == WORDSPERLINE) { *(t++) = '\n'; words = 0; } } } } *(t++) = '\0'; } --- 181,223 ---- *(t++) = '0'; *(t++) = 'x'; } ! if (xbitmap) { ! if (*(s++)) ! i = (i >> 1) | 0x8; ! else ! i >>= 1; ! } ! else { ! if (*(s++)) ! i = i * 2 + 1; ! else ! i *= 2; ! } if (++bits == BITSPERDIG) { ! if (xbitmap) { ! t++; ! t[-(digits & 1) * 2] = *(i + HexDigits); ! } ! else *(t++) = *(i + HexDigits); bits = i = 0; ! if (++digits == digsperword) { + if (xbitmap && (s >= F + PIXELS)) break; *(t++) = ','; digits = 0; ! if (++words == wordsperline) { *(t++) = '\n'; + if (xbitmap) *(t++) = ' '; words = 0; } } } + } + if (xbitmap) { + sprintf(t, "}\n"); + while (*t) t++; } *(t++) = '\0'; } *** uncmain.c.dist Thu Oct 24 03:28:07 1991 --- uncmain.c Thu Dec 22 09:58:34 1994 *************** *** 28,33 **** --- 28,35 ---- int outfile = 1; char *outname = ""; + int xbitmap=0; + /* basename of executable */ char *cmdname; *************** *** 59,64 **** --- 61,73 ---- while (**argv) if (*((*argv)++) == '/') cmdname = *argv; /* find the command's basename */ + + if (argc > 1 && !strcmp(argv[1], "-X")) + { + xbitmap++; + argc--; + argv++; + } if (argc > 3) { exmh-2.9.0/misc/exmhwrapper0000755000170700017070000000064313201227060015234 0ustar valdisvaldis#!/bin/sh displayfile=$HOME/.exmh/.display if [ -e $displayfile ] ; then display=`cat $displayfile` if [ "$display" != "" ]; then /usr/bin/wish -f -display $display < $displayfile exmh rm $displayfile exit 0 exmh-2.9.0/misc/mhthread-manpage.html0000644000170700017070000001426413201227060017040 0ustar valdisvaldis #!/usr/bin/perl -w =head1 NAME

SYNOPSIS

        mhthread [options] +folder
        mhthread [options] /path/to/folder

options accepted: [-debug] [-no-write] [-fast] [-lock]


DESCRIPTION

This will thread an MH folder. It re-orders the messages (as sortm(1) would do), and annotates each one with a new header, ``X-MH-Thread-Markup'', which can be displayed by scan(1).

Together, this results in the messages being displayed in ``threaded'' order, as in trn(1) or mutt(1).

Sequences will be rewritten appropriately. The folder will also be ``packed'', as if 'folder -pack' had been run; see folder(1).


RESULTS

Here's some sample output from scan(1), after threading the folder:

  430  03/23 mathew              3  [Asrg] Re: [OffTopic - NNTP]
  431  03/23 Kee Hinckley        5  |- [Asrg] Re: [OffTopic - NNTP]
  432 -03/23 Chuq Von Rospach   11  | |- Parameters for success? (was Re: [A
  433  03/23 To:Chuq Von Rospa   4  | | \- Re: Parameters for success? (was 
  434  03/23 Matt Sergeant       3  | \- Re: [Asrg] Re: [OffTopic - NNTP]
  435  03/23 Chuq Von Rospach    7  \- Re: [Asrg] Re: [OffTopic - NNTP]


OPTIONS

-fast
Use an on-disk cache to speed up operation.

-lock
Use a folder-wide lock-file to synchronize access to folders, so that multiple processes will not stomp on each other's changes or cause folder corruption. If you use this, you should ensure that you also use a locking version of other tools, such as the lockedrcvstore script that comes with ExMH (typical location: /usr/lib/exmh*/misc/lockedrcvstore).

-no-write
Do not rewrite the messages; instead, output a line for each message noting the actions that would be taken.

-debug
Output debugging info to stderr.

Note that options will also be read from the mhthread entry in your .mh_profile file, in traditional MH style.


INSTALLATION FOR SCAN

To display the results in scan(1) output, use something like the following for the subject-display part of the scan.form file:

  %(decode{x-mh-thread-markup})%(decode{subject})

If you do not have a ``scan.form'' file of your own, you will need to set it up. This functionality is accessed using the -form or -format switches to the scan(1) command. To use this, copy the /etc/nmh/scan.default file to your ~/Mail dir and modify it with the above line, then add

  scan: -form scan.form

to your ~/.mh_profile.


INSTALLATION FOR EXMH

Add the following function to your ~/.tk/exmh/user.tcl file:

  proc Folder_Thread {} {
    global exmh
    Background_Wait
    Exmh_Status "Threading folder..." blue
    if {[Ftoc_Changes "Thread"] == 0} then {
      if {[catch {MhExec mhthread +$exmh(folder)} err]} {
          Exmh_Status $err error
      } else {
        # finish off by using the ExMH packing logic to redisplay folder
        Folder_Pack
        # then show the first unseen message
        Msg_ShowUnseen
      }
    }
  }

Next, you need to rebuild the tclIndex file. Run tclsh and type:

  auto_mkindex ~/.tk/exmh *.tcl

Now add a button to run this function. To do this, you must exit ExMH first, then edit the ~/.exmh/exmh-defaults file and add these files at the top of the file:

  *Fops.ubuttonlist: thread
  *Fops.thread.text: Thread
  *Fops.thread.command: Folder_Thread

Restart ExMH, and there should be a new button marked Thread on the folder button-bar. Press this to re-thread the current folder.


NOTES

The threading algorithm uses the In-Reply-To, Message-Id and References headers. Thanks to JWZ for guidance, in the form of his page on threading at http://www.jwz.org/doc/threading.html.

The 'X-MH-Thread-Markup' headers are encoded using RFC-2047 encoding, using 'no-break space' characters for whitespace, as otherwise MH's scan(1) format code will strip them. Here's an example of the results:

  X-MH-Thread-Markup: =?US-ASCII?Q?=a0=a0=a0=a0=5c=2d=a0?=


TODO

dealing with private sequences (stored in .mh_profile); limiting displayed thread-depth to keep UI readable (so far has not been a problem).


BUGS

duplicate messages will always be shuffled in order each time mhthread is run, due to handling of identical Message-Ids.


DOWNLOAD

Latest version can be found at http://jmason.org/software/mhthread/ .


AUTHOR

Justin Mason, jm dash mhthread dash nospam at jmason dot org


VERSION

version = 1.5, Apr 25 2003 jm

exmh-2.9.0/misc/README.archiveoldmail0000644000170700017070000000230413201227060016602 0ustar valdisvaldis README.archiveoldmail Perl script to walk through all your folders and move old messages into subfolders. Purpose of Hack --------------- exmh gets slower and slower as folders get large. This is a script you can run from cron to move old messages into subfolders What You'll Need ---------------- It's written in perl and uses mh/nmh. Instructions ------------ Take a look at the script and make sure the MHPATH and MHLIB variables are correct for your environmment. There is a hardcoded "60" which says that any messages more than 60 days old will be moved. That can be changed. The naming of the subfolders is done using a -format argument to 'dp'. This can be changed easily. The script uses refile, so it has the same characteristics as that program in prompting you to create new directories if called interactively, but not if stdin is not a tty. I call it from a cronjob which runs at the start of each month. Limitations ----------- If exmh isn't actually running when this script runs, its caches will not be updated. Suggestions ----------- You may also want to add this line to your .mh_profile: Folder-Unseen: !*/old* * Author ------ Chris Garrigues exmh-2.9.0/misc/gbuffy-use_mhunseen.patch0000644000170700017070000003256613201227060017754 0ustar valdisvaldisIndex: config.c =================================================================== RCS file: /home/zamboni/cvsroot/tools/gbuffy/config.c,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 config.c *** config.c 2000/10/16 18:13:09 1.1.1.1 --- config.c 2000/10/19 21:17:54 *************** *** 15,20 **** --- 15,21 ---- static char *DefaultsFile; /* = "GBuffy";*/ static char *get_defaults_file (); + void configure_get_mh_unseenseq (); static proplist_t pl_get_dict_entry (proplist_t dict, char *key) { *************** *** 357,362 **** --- 358,366 ---- return NULL; } + /* Get the unseen-sequence for MH */ + configure_get_mh_unseenseq(); + PLRelease(top); return box; } *************** *** 406,409 **** --- 410,437 ---- strncat (path, "/GBuffy", sizeof (path) - strlen (path)); } return safe_strdup (path); + } + + /* Gets the name of the unseen sequence from the MH config file. + * If multiple names are defined, we use the first one. + */ + void configure_get_mh_unseenseq () + { + char *tmp; + tmp=get_mh_value("~/.mh_profile", "unseen-sequence"); + if (!tmp) + { + if (errno == ENOENT) + { + fprintf (stderr, "-E- File ~/.mh_profile does not exist\n"); + } + fprintf (stderr, "-E- No MH unseen sequence defined - not using it\n"); + } + else + { + /* Get only the first component */ + MH_UnseenSeq=safe_strdup(strtok(tmp, " \t")); + safe_free((void **)&tmp); + } + return; } Index: count.c =================================================================== RCS file: /home/zamboni/cvsroot/tools/gbuffy/count.c,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 count.c *** count.c 2000/10/16 18:13:11 1.1.1.1 --- count.c 2000/10/23 15:50:24 *************** *** 10,15 **** --- 10,17 ---- #include "gbuffy.h" #include "rfc2047.h" + void process_message (BOX_INFO *mbox, GList *headers, char *path, char *fname); + int parse_mime_header (BOX_INFO *mbox, GList *headers, FILE *fp) { static char *buffer = NULL; *************** *** 25,31 **** while (*(buffer = read_rfc822_line (fp, buffer, &buflen)) != 0) { ! if (!strncmp (buffer, "Status:", 7)) { status = TRUE; if (!strchr (buffer, 'R') && !strchr (buffer, 'O')) --- 27,34 ---- while (*(buffer = read_rfc822_line (fp, buffer, &buflen)) != 0) { ! /* Only check Status: header if we are not using an unseen sequence */ ! if (!strncmp (buffer, "Status:", 7) && !MH_UnseenSeq) { status = TRUE; if (!strchr (buffer, 'R') && !strchr (buffer, 'O')) *************** *** 158,173 **** DIR *dp = 0; FILE *fp = 0; char buffer[STRING]; ! char garbage[STRING]; char from[STRING] = ""; char subject[STRING] = ""; char path[_POSIX_PATH_MAX]; - char file[_POSIX_PATH_MAX]; int found = FALSE; int status = FALSE; int is_new = FALSE; int mailfile = TRUE; int count = 0; struct dirent *de; struct stat s; struct timeval t[2]; --- 161,178 ---- DIR *dp = 0; FILE *fp = 0; char buffer[STRING]; ! char tmppath[_POSIX_PATH_MAX]; char from[STRING] = ""; char subject[STRING] = ""; char path[_POSIX_PATH_MAX]; int found = FALSE; int status = FALSE; int is_new = FALSE; int mailfile = TRUE; int count = 0; + char *mh_unseen_seq; + int mh_msg; + char mh_msg_s[STRING]; struct dirent *de; struct stat s; struct timeval t[2]; *************** *** 197,257 **** mbox->num_messages = 0; mbox->new_messages = 0; - - dp = opendir (path); - if (dp == NULL) - return 0; ! while ((de = readdir (dp)) != NULL) { ! mailfile = TRUE; ! if (mbox->type == GB_MH) { ! char *p; ! ! p = de->d_name; ! while (*p && mailfile) { ! if (!isdigit (*p)) ! mailfile = FALSE; ! p++; } ! } ! else if (mbox->type == GB_MAILDIR) { ! if (*de->d_name == '.') ! mailfile = FALSE; } ! if (mailfile) { ! mbox->num_messages++; ! if (headers != NULL || mbox->type == GB_MH) { ! /* Ok, we need to get the From: and Subject: lines */ ! if (mbox->type == GB_MAILDIR) { ! snprintf (file, sizeof (file), "%s/new/%s", path, de->d_name); ! } else { ! snprintf (file, sizeof (file), "%s/%s", path, de->d_name); ! } ! fp = fopen (file, "r"); ! if (fp != NULL) { ! parse_mime_header (mbox, headers, fp); ! fclose(fp); } } ! else { ! /* For maildir, if we aren't getting headers, we just count ! * everything in this directory as new ! */ ! if (mbox->type == GB_MAILDIR) ! mbox->new_messages++; } } } - closedir(dp); - /* Restore the access time of the mailbox for other checking programs */ t[0].tv_sec = s.st_atime; t[0].tv_usec = 0; --- 202,261 ---- mbox->num_messages = 0; mbox->new_messages = 0; ! if (mbox->type == GB_MH && MH_UnseenSeq) { ! /* If the unseen sequence is defined, count according to that */ ! snprintf(tmppath, sizeof(tmppath), "%s/.mh_sequences", path); ! mh_unseen_seq=get_mh_value(tmppath, MH_UnseenSeq); ! if (mh_unseen_seq) { ! /* Seed the sequence string to the function that parses it */ ! expand_mhseq(mh_unseen_seq); ! while((mh_msg=expand_mhseq(NULL))) { ! snprintf(mh_msg_s, sizeof(mh_msg_s), "%d", mh_msg); ! process_message(mbox, headers, path, mh_msg_s); } ! } ! else { ! /* There are no new messages in this folder */ } ! } ! else ! { ! dp = opendir (path); ! if (dp == NULL) ! return 0; ! ! while ((de = readdir (dp)) != NULL) { ! mailfile = TRUE; ! if (mbox->type == GB_MH) { ! char *p; ! ! p = de->d_name; ! while (*p && mailfile) { ! if (!isdigit (*p)) ! mailfile = FALSE; ! p++; } + } + else if (mbox->type == GB_MAILDIR) + { + if (*de->d_name == '.') + mailfile = FALSE; } ! if (mailfile) { ! process_message(mbox, headers, path, de->d_name); } } + closedir(dp); } /* Restore the access time of the mailbox for other checking programs */ t[0].tv_sec = s.st_atime; t[0].tv_usec = 0; *************** *** 261,266 **** --- 265,304 ---- utimes (path, t); return 1; + } + + void process_message (BOX_INFO *mbox, GList *headers, char *path, char *fname) + { + char file[_POSIX_PATH_MAX]; + FILE *fp; + + mbox->num_messages++; + if (headers != NULL || mbox->type == GB_MH) + { + /* Ok, we need to get the From: and Subject: lines */ + if (mbox->type == GB_MAILDIR) + { + snprintf (file, sizeof (file), "%s/new/%s", path, fname); + } + else + { + snprintf (file, sizeof (file), "%s/%s", path, fname); + } + fp = fopen (file, "r"); + if (fp != NULL) + { + parse_mime_header (mbox, headers, fp); + fclose(fp); + } + } + else + { + /* For maildir, if we aren't getting headers, we just count + * everything in this directory as new + */ + if (mbox->type == GB_MAILDIR) + mbox->new_messages++; + } } int external_folder_count (BOX_INFO *mbox, int force, GList *headers) Index: gbuffy.c =================================================================== RCS file: /home/zamboni/cvsroot/tools/gbuffy/gbuffy.c,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 gbuffy.c *** gbuffy.c 2000/10/16 18:13:12 1.1.1.1 --- gbuffy.c 2000/10/16 18:19:43 *************** *** 15,20 **** --- 15,21 ---- char *Maildir = NULL; char *Spooldir = "/var/spool/mail"; char *DefaultNewserver; + char *MH_UnseenSeq = NULL; int Vertical = FALSE; int PollTime = 10; int PollId = 0; Index: gbuffy.h =================================================================== RCS file: /home/zamboni/cvsroot/tools/gbuffy/gbuffy.h,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 gbuffy.h *** gbuffy.h 2000/10/16 18:13:13 1.1.1.1 --- gbuffy.h 2000/10/17 14:57:11 *************** *** 73,78 **** --- 73,85 ---- char *face; } MESSAGE_INFO; + typedef struct _mh_seq + { + int first; + int last; + int cur; + struct _mh_seq *next; + } MH_SEQ; /* Global Variables */ extern int Vertical; *************** *** 83,88 **** --- 90,96 ---- extern int PollTime; extern BOX_INFO *MailboxInfo; extern BOX_CLASS MailboxClass[]; + extern char *MH_UnseenSeq; #ifdef DEBUG extern FILE *debugfile; extern int debuglevel; *************** *** 116,121 **** --- 124,131 ---- char *gbuffy_expand_path (char *s, size_t slen); void safe_realloc (void **p, size_t siz); char *read_rfc822_line (FILE *f, char *line, size_t *linelen); + int expand_mhseq (char *s); + char *get_mh_value (char *file, char *attr); /* nntp.c */ int nntp_get_status (char *group, char *npath, int article_num); Index: lib.c =================================================================== RCS file: /home/zamboni/cvsroot/tools/gbuffy/lib.c,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 lib.c *** lib.c 2000/10/16 18:13:15 1.1.1.1 --- lib.c 2000/10/23 15:53:40 *************** *** 24,29 **** --- 24,31 ---- #include #include #include + #include + #include #include "gbuffy.h" *************** *** 187,191 **** --- 189,377 ---- } } /* not reached */ + } + + /* Expand an MH sequence into individual message numbers. The first + * call sets the sequence specification, and returns 0. Subsequent + * calls must have a NULL argument and will return succesive elements + * from the sequence. After the sequence is exhausted, NULL will be + * returned. All the elements allocated for the sequence are freed + * as they are returned, so after the last call (the one that returns + * NULL) there's nothing left to be freed. */ + int expand_mhseq (char *s) + { + char *seq_str; + static MH_SEQ *seq=NULL; + MH_SEQ *tmp, *last; + char *p, *q; + + /* If a string is given, initialize things */ + if (s) + { + /* Clear up linked list of subsequences */ + if (seq) + { + MH_SEQ *t = seq; + while (t) + { + seq=t->next; + FREE(&t); + t=seq; + } + } + seq=NULL; + tmp=NULL; + last=NULL; + + /* Allocate the new seq specification */ + seq_str=safe_strdup(s); + + /* Allocate a new linked list of subsequences */ + /* First, split by spaces */ + p=strtok(seq_str, " "); + while (p) + { + /* Create new element and link it in */ + last=tmp; + tmp=safe_calloc(1, sizeof(MH_SEQ)); + if (!seq) + { + seq=tmp; + } + else + { + last->next=tmp; + } + tmp->next=NULL; + + /* Examine the current subsequence to fill the data structure */ + if ((q=strchr(p, '-'))) + { + /* Subsequence with more than one element, of the form first-last */ + *q='\0'; + tmp->first=atoi(p); + tmp->last=atoi((char *)(q+1)); + tmp->cur=-1; + } + else + { + /* Single element subsequence */ + tmp->first=atoi(p); + tmp->last=tmp->first; + tmp->cur=-1; + } + + /* Get next subsequence */ + p=strtok(NULL, " "); + } + + FREE(&seq_str); + return 0; + } + else + { + if (!seq) + { + g_print ("-E- expand_mhseq(NULL) called without seeding first\n"); + sleep(1); + gtk_exit(1); + } + /* Get next element */ + if (seq->cur < 0) + { + /* First element in this subsequence */ + seq->cur = seq->first; + } + else + { + (seq->cur)++; + /* Check if we need to move to the next subsequence */ + if (seq->cur > seq->last) + { + MH_SEQ *t; + t=seq; + seq=seq->next; + /* We free elements of the list as we go past them */ + FREE(&t); + if (!seq) + { + /* We are at the end of the list */ + return 0; + } + else + { + seq->cur = seq->first; + } + } + } + /* Return the current element */ + return seq->cur; + } + } + + /* Get the value of the given attribute from a file in MH-attribute format (attr: value). + */ + char *get_mh_value (char *file, char *attr) + { + FILE *f; + struct stat s; + char path[_POSIX_PATH_MAX]; + char line[2048]; + char *p; + char *res=NULL; + + strfcpy(path, file, sizeof(path)); + gbuffy_expand_path(path, sizeof(path)); + if (stat (path, &s) == -1) + { + /* fprintf (stderr, "-E- Error accessing file %s\n", path); + perror ("stat");*/ + return NULL; + } + else + { + errno=0; + if ( (f=fopen(path, "r")) == NULL) + { + fprintf (stderr, "-E- Error opening %s\n", path); + perror ("fopen"); + return NULL; + } + else + { + while (!feof(f)) + { + if (fgets(line, sizeof(line), f)) + { + line[strlen(line)-1]='\0'; /* Remove end-of-line character */ + /* Split into tokens */ + p=strtok(line, ": \t"); + if (p) + { + /* Look for the attribute name we need, case-insensitive */ + if (strncasecmp(p, attr, strlen(p))==0) + { + /* Get the rest of the line */ + p=strtok(NULL, ""); + if (p) + { + SKIPWS(p); + if (*p) + { + /* Not empty string */ + res=safe_strdup(p); + break; + } + } + /* We get here if the attribute has no value */ + fprintf (stderr, "-E- Null value for attribute %s in file %s\n", attr, path); + } + } + } + } + fclose(f); + return (res); + } + } } exmh-2.9.0/misc/jpilot-lookup.tcl0000644000170700017070000000146413201227060016262 0ustar valdisvaldisproc jpilot-addr-lookup {n} { # look up addresses in jpilot's address book Exmh_Status "Querying jpilot for $n" if [catch {set jpilot_results [eval exec query_jpilot.sh $n]} e] { Exmh_Status "Error executing jpilot-dump: $e" return {} } # the jpilot_results looks like this: # e-mail@add.ress\tlastname firstname\tcompany set result {} foreach i [split $jpilot_results \n] { if [string match {*@*} $i] { lappend result "[jpilot-addr-formatformail $i]" } } return $result } proc jpilot-addr-formatformail { line } { global addr_db set s [split $line \t] # s will contain "email" "lastname firstname" "company" set email [lindex $s 0] set name [lindex $s 1] set company [lindex $s 2] return [LDAP_Entry_FormatForMail $email $name] } exmh-2.9.0/misc/README.ns-exmh0000644000170700017070000000021213201227060015172 0ustar valdisvaldisThis is an alternative to comp.pl/Muttzilla, written by Larry Daffner, vizzie@airmail.net. Instructions are included in the archive. exmh-2.9.0/misc/mhutils.tar.gz0000644000170700017070000002030513201227060015555 0ustar valdisvaldis‹,ÆŸ:ìÿ©Æ¾–c#?ä¦5a…F¸l8¢ø¡º>¬íbãyù¼Ì]€ICü´Ë³§‡uVYß{õÓׯöÎ[¦ã¶šâÁ¨ÂüÙ‡kÿN—³êðìƒ6¨D6Ó`WÝ-^@Ùr}X< [‰’ãl˜„ChbëÃA4qF¸qltF¬J ÞõfÁ‚ׇ­æt2Tº3ªÐº²…ÑóãÕÖ¯Òõb­:û =¨ÕÒQÙx¼‚ÐñbVÙÜ„Å|ð*»…Îè,Šù”U@¦Á¡Jmt^NŠÃ\¢—°p—½±ãÁViàò)ð½;@~Äâ‰Áôþ84§;¬û>‹\ÿ´VÎY˜XZˆßF®Å`(\à$ÏGówú¬r+ aæÆÈŒâßVFä¶®œþB~r-à2ýßéöHÿwt]ïuº¨ÿÛº¶Òÿ7q}«þÏû •:;NbæÄ,äSÿ|ÆxÂat%㤠Sz¯ŽºLhˆÇìø,µ%Í•1!c‚mwÙ!¡’.àœðqÊŽ9¨cÏñÆÌôlзf4É:¹gÓ³Që×"]÷°µµþðá÷7O]¿·‰ÊqÌÊLÝä•Óÿ×þß!¿ß¿ôü§«iF·‡ñ?ý3®Ó(©ë®ÿýÃúc*é‡RêZÑŸè2v‰ÿgh]Äÿ½^·m`þ¿Ç…+ÿﮫùÊкgì4tâL&8pÿò'û/pF"³‡¾íŒ‹,p„ÝO>öÙÿ¼îÀˆ{ä‚ †™á8A{Íb°Ë·œÑ“¾6ñ/æÔñ8=ó˜£ãGžŽ´ÖYŠÚQ%xufoc³üà ='†ÇÁ}ñèÑ4uYõÆ©ÿšú¤ :¸°h‡Ü\ÏŽ¬Ç´bô~skÈÜZt¡ã œ`BPnl~.yf ŽëM¢À´,Y‹ž&O=ŸÎî·Ž.0ἦ׼ óÍþ­\ÐôŒ=t¼`@^ìnê*ÏgbpT-CÜ¿Vy´”,ϲ.¹¤yæÊPâœ5ÐÅoÝy˜KӜӿ@Žåî÷̺æŸoá"lîò˜§–çm$Èm+¨Õu­WÑþKÁþÎs\–ÿ¯OæÿÁÐ:˜ÿ1:«üÿ\W³ÿoHç) ùdÖ6Á Ÿ{ÿD3õ÷;)˜ÉÁ\œZ¹m¦\]7v-«ÿüžs\Rÿ©ëm=ÿûX ªw»ýUýÇ\ ÿƒVl¹íf›”þ©Cµ ï"¾Ãæª=¥Š{_,ùüãå€) “y~Ì&扈ٶX䌽&ÛÍŠbÔ5v ªËc*8»†ÀVvE…orb<<ÀxF¢Ë:{ Q—Ìa/pXù00ÁNåÌ66Œ¦ûÌFÁ ý(ŸNɲ١yÊš˜^u‹0«·³0ø:CŽ¡c$3ƾ¾kd†`¼ÞŸ:àBÁšcÑG¶žNðq0hèçR5ó/Ü’}¸ÄV6Œ=`-›Ÿ´¼ÄuÙ=,ìÔ7ÍQ2GЉè*>Ë™ãr™ÆöM2lÇåÞдùÉGvž³wÁ¨!-'0¬|ΤÍ-Eܳ^dRîÉÄô€RmóÀŒ¶²!ÿ—Òÿ˜©Ð¯Iá^Zÿß×Óúÿv¿ù¿.æWúÿú¯‚ÿúÿ¾ €y&uoeýa¥lûåÒ±ÿE½àä^Ž­­õVkã·r‰†T61;T@]ˆôÜ0ä±]x_釿ǕÖÿN:×3Çeòoè™üwpœÞî­âÿ›¹Ëÿ«wƒu½L±ëµjƒu˜i¥nñRò[Ñ$´à'Á÷žå¿wAü×ÓÓ÷?1ò£úßUýÿÍ\wDdal%1¼WŸž}™®ƒï”Jò5q?JJ¹wÅdãIRJ dS˜” åª9XØ„&bf`ÆÖä;Ìq±þoÝ^OéÃ0ðý~gõþ÷Í\ûžÍ¿ì€„{#gܴʃ¿~•Ÿ1íÖšøSÞ’¨mY'Qèûq+öý”ãZjæúI9äqèpª~µéD¨Öõ&ý¯l;£kX¬Ê–lÉè^ª›æ[:ü¿Çôí½½£Ý/)FcÁÀûÌÐwôþN·ƒòAÖ»uCct‹Ïã­ÎàW£Ì0;³&ÀA›OùÈLÜ8z;ße­M6`•çq•ÝÍV™²p…Æ<Úò¡áˆN£j»å-vâ;¶\gò!›N†B&#þ™Få¡¡`ùê0fKÃmÇŠ‡À¬á«æz±¹.'ÿÄÏðÄèëÂ=·»ýz»gd»nw·¡¡§ö+ =öêÝË—YŬžáÖŸó8W,“U`$öЗïQ ‚À¾yyÈ]& û8€SsC!ªí¡£õêí~¶‡Ž®Õ;í~~Qz–’ÌxRg•–¤WEÎï܉ŽkàH—{ò¾–/Ñk‰ÌÂ(; ä(ÜÁ9îbKb„Êã™gN¹(Pž«%b£ÐŸRÙ\DÉQ±µ‰ô)ðŠv„ ˆú'à Çãvr,bÙrʤCT%žl]‰©`ÐWAbÏ@ñ~ äðÓMxµò¿tL Œ…‹dUfÈ\©‰'ñ¸r ¯Ñ.Zyz>f¡÷^½Þ{õ¶&»ÔÆFtl #£Ø†Á0Gc¯ÁP´Xavfû€ÐÀ‹¿3˜r(?ŽøçAŽe`ma쪲`}ìC\©¥û a£ój•ˆ¸¹Y»‡HͯH0¡†T£'^|; &þú\,X¨sú=¯Íu}F›ÇmPÐ;]mÇX¢ÌµºÞÍ)s¸MÂ]dz\°ñ¬"6ÒœT ­áÈ2´N_4+‰6´x ÕqUõñë_†û¯ž½f›€¢/uöü%¾X°9á&–"(í+ôø=BYVúÏê3D/Ì™ò¡xìr¨Ïö_î¤@¨t¡Úr–÷`R[/Œѭ·uy^$ $6«éÓx074lÆÐ9aÕQ€õØ]g÷àèÈZ­ ˜Vc²va-ú5R·SÐê‘ʬ2‰v@‡ôkò‰|ýBDÝ0óÛÃw{Yñ‚fMÂ ÖÆáFÝ»Çæ;^o l¤·f­£èýý7 jà5ªk­OLîI¢AC£ÆÎT‹éÍi PWÆm7¯R®…‹Ý£m¡¶âÆžî²M;€51âͬ…˜RÀ~ôöpÿÕó»´kê›á1ˆRÖ“>‚æQ5£wUÉõEÉñ¿¹/ëF{?|óúhÿ—á›Go_ ý )h`ƒý„*ª|J<`>{ôòh/kN‘;ÓîDC,ßkŸB¬GV+Oì =–!ðŸX诅d=l^hÆYYThŠAY€qfñ{w…ª­§]¶3oç/ÓlÎ,^#n™ ”:HX’%]2N£qn hFE–ý‹D\(l÷ûu£Û/¨i4^2¦eñ)Ae?ék0â|â¬Gƒ5¦NkCjì£Fm©§K°‰-¤ò¬Ú\êM‚cB;ŠGóúqû™¦+Ï޳><Q¬áqð“cŸe¨÷ d‡^O=’¾ÃÐ|F¢•.ÆÌWöÈS¾:î*‹Âh`ü~ˆZÀÌ­"0Â…ÊW#¥e*W…w,ü‡ô㈊6%JXý¸%èV¬Ž˜*ɉ¸pÂqK=¶Q €@|B˜Õ‘nKçs,&ŽY:`‚„®žyX©$‰Ñ½H'ƒ®'‘Ôr4ë&ã'<<£ÚQcåD¤ª¬ØÏðÛ?¨?ÅÐ+ÐOJÍœº)JLþï¹°½¸u˜•©%삽ò(V/ý˜zؤUÜŒÛÆ#DL'ÈvÐå½ÈW~‰íXü^ûØŒO@ƒ[@ȨÅCAízÑ­ ÛihFÝèéGñϨY©&—è7ÔKçmÖ—Ü_œ$@B©˜_˜-ÀÚ¸{ÇxbÆ™©$ *­·’u/¥ Xv,¢¦ôEÁ S)ÔÂF Š=ÿ𼞂m‘"É¿¢%+Óh3˜Ð÷,:á¡‘dEX|—î êP<°,Lgœ1Õª0ÖƒÂ#$¿µã¢N™÷wªgºDƒ虈pVîºR JΞ,B×[`wG¦<§ÄXÖJJPÅ¿u-s¡‘/ï¨Ed~@j†¯ê LÔboàr@Ò§è ”æý€ÒR@©é¥ö‰Š]h´Òyš©:géÏ«¸[é¶„R]hÿ·;!³¼²Ø ø¹#l^^ý«-jélÄ­*ê…I zŒ^/Kð½n½­u²((A‘JøÆ*“ž2µžËÚ~ßO1½º$ÞÄ~—íŠU,óåT‚õÊ~ÜLÂòO¸qYþv)ƒÏ%r¿Ý¥ËòayLs®ßüRÀ˼l³ov WôôÒ¼vÎÙ˯cybùO»yjÊ+ºzéð+Ñ9¿ØéÛ’Jâ\ȆÍüKÌCÏtå{RCá»ÌÉ“ˆöC|³º(Z5•Ù–éÙ[Hm«™¿9·.µ”ºYÝ6 ÙíeïïtÚK’qËÏ*….:œ”¦‚UûQû•Ö‰¶"lh!ãU²Qòˆó?xL…t–psþ_8ó'ƾ —3cØþÆwÝ·h+L×òû¶ÐðErOnÜ“?KîIžÜ“än/"wn`ŸénG×’»ß®÷·3rÃív73uÒø˜™Ðsv°wtôèù Û®8Â@Á†XB% †" H-‰"ee¹/¬,Êî¬$7ElÓa'KŠÁÑÞK3‹çd® ¼ð“:æ±Ë¥ùº¡À.‹-ü6ì1·åûZý~z*¢xk7kÎôÌpJö½‘?Óÿä壣#&ûŸàë«ïÉ(Ë!ó¬¾K'D#ÄáÓ½Çïžgà„·ùq2F~Û-®Ú]ÐËK¶©ë½ºnè9Q6:u½=#Ì‚a†2”¡·ª¢GÆ*ØExZ³“7Cg‰ô ßbê81È;¿×2iŸ? ‘®‰rl°1}–îÄd[RßgVº®Z¦2ò¤êXü6ã8¬eŒãyqд» x¼§cl™–Æ¡Ÿ „' ?7‘«\>7ª–ª×9¾ 3BÓ~³R‹Eî _ ÔI· NŠ£äÉh{§£-v;u#W,··¥g ?F±`' ­‰vÚžm N©i+ÿøYÔBrͶS9€x~éAìb9Ùî×õûy9Ù¾_o÷ E*ß$ý)<}£WÍÁï%_'«ÑØ#ŽÅS¹ƒ¹|‹ãëv¶sâØ ¨. 'ƒ[ÒĈ\¨IQ¦aáGä"Uî‘%5è+7òû8uò°EÌ1­ÉÐÛCsP"ñ:%½Ji ï>ýn>êÀLªþ$ÁèË‘\| /pÒ’µ&{Do!ÿ21a6Ì*ÑLü˜ (bn7ñ >⣃rFºÄ„ç(È+@Å$.؈‰ïä`³êÃgfº 4/U¼õ=.²>SŽðÄ1šä‘zA‘¹|D_:–s6u—k¢™zèÃb eÏèô\/ê—;U+klfQF~Ð&‹T5ÔþÈ'“ZÙK¯ŽçÄŽé‚öd´ƒ4ÄBÇ;*ÖÌ'.ðI€áØ'À6}°‚H1Ž5¤QÂm6^IA¶:ÕÂK&KâZÚB) ÜzŒþ½0è¥g‡{{Õ{1éñR<(€P!•ú[D›¨$Êß#êÒ†l§$G‰r)ˆMlñÉö)©V¬¥©-g´+á/iàÏÀuès¥Q`†Y´#×€…;Yà(ÑÌSiI«¢ÕH9"yÆ•afÓÉmPb)­ÆRx¤ [$|U=ÍL êÖr§8èÏ8!OÖ<Ì,¡•‹´å`\`eÏ@³0CN&ô*}Í‹è .#‡æÐŽR;r¤^±ÍØ”îdò<p'ÕÏQ›P1Ûhl`Ò¶°TÌ'ç Ó—J¦"Ajõ‰Dx]¥¨@kM…únö¡K›Ÿ´ Áå¸910cß©µ¬™ˆC­R¯ÔªŸ·ôZnlxÐЯ†h\=h7]eMbe—®&pñ"òÂê5$ßü|¬ÈëHÞ"£ç@ Ý Å!¥‹/Ht̲i&.ã¡ø‚I•ÊöæÓöd.¸M¤ö“ßl £Â@¾¡/̃ªžkÇŸ†ø¾z®QÑ'EYõJˆe?2m¡”“IŸU™—%N¡ ÄÏ\ÜuI,]HM%^äüO¨ I¤ŒTš¾-,V."xaƒÄ’»fÄ-µ&Es@ê…žIí¬çga™3×AJ ibp`™cŸ(„Ð<•ü^08y6)Ñ h§? _#ûr´€SdDJà—$>¤¥4ȧûçÙäPÀÍk·9†Q^šœ!“…B…0Á‘Üù C!ç8‰e…°I¡rÔÁ‹F®43cËŽSË €¿!èJ=#ïb|U¸’zçV_TLó¹qé­£S­.ʰ[FÕ,ÃñæÿÚ»ÚÞ6n$üyù+ö| j]¬µS\¯8#=\àˆÑºÉE.zEa+‰’Òî âʪ®H{ç™r¹’Ü¢@Ûà±"wùΙá3|¦GKß‹YII\ñ%Cÿù½ìÓ‡,݈ýûõ¤Ï7 ¯|Ôˆ5ÔK‹kt|¬£-ÍV.| Ûœtåä’=±uUÑQVç~J._Õõ<œ}ZndƒžJ^â®ÜÙ~Q9j´þšô„‰‡ÎŽÊ%4Ôr¦o¨ÍÞ_\ô|öÐtç¡qPÓ ½*®÷CòÍ/{íß\2øòæí·¯\ˆ¡RrÉZÈL~ ¿ûrÙlýéFZeYë::¹¯(M‡¤ûÎåm«:£"y{[º‹ÉÎÄÎ`±¨ULÆÃ|ÄÑP:’‹ÔÖó”-æ1Ë´Çœ:öáð.Ðtöù䔿`ÏÊ£‘ýê«MÿÁMñbóýzI¸UЬ-~‡6~åý÷Åßñ[ßþés¼ÿûìøþïÏIý]Øpö½•Ê’ôqú²Ø»¹Ø^$§6yÁ¶KfÉôª.Ë¢1°µ§¯Iœ¾¿uÓÁ5¦?2oª½óVMЪ¦bR` /–g?~¿²SR èÇEÿŸ÷Ïž|HŸpI"òb|0®ngïòn€ºFëTL“½ô ç4 šõ±×èLžÿ/.Þ]¿|u{ýG´ñËü˜?íûßÏÿÁøïŸ=?â?ý)é¶p#»Xä•­×î1¤Öù—š0ÓŽ[ëÿ†dÌÝÌ’VØVÉ÷Øö¡^< –Ю|aþíx/npÛ{#ÇUê‚ñMsG2|Á!@éxëÈ(tÆ*ȹ‹lÉ~#íÉÃ÷ȣº•¼é“«!6e‘‡;çÂr=’‹#3YØŠáÂfpTL‡ö"µÆV0&BÄ™:‘· È;ê«Þø3.}”‰¡ïëÒnDÍ©Òm½–ÓT–~W¯åÞÀuƒ4º9ä§`*â?^>êBvõü£3}ãJ ƒ:1€ç‰Ænït81}\§Q=¶~ÊœQ´,T1©|ÅŽÓ4?`J4u©‹õ›öùžmîþÒcÀGêL:±vÁ½2¬“’±^ŒÓ|áøªc'•‹ø¦ Òù(˼ª7Ôy-/ÖjËk%×xL2’Æ‹HgÒß,ÐøÇ«z‰JòÊ01PEý~+’¤ºòú¿—kRNmfÇk¢Ö«Áëtp}÷Í[±ö‚_Ö2DΙ¨£;è#›ó}eáR^1Ðí–)xlsž<¦7å(±Å;¢‡ŽêªÉ‰jbà Ü ›Ý朸þ8Z2êY–¾•0\žˆ2®•I#z„6¸e¦º9[ (¦qí ±KA‘ôÍjú}“ïÏ¿Ìù_c¾åh L˜Ï‚æü¤-WÅÿ$•ZÑÞ}µX¡Z;·.1 hبEKUõ,Ê·²£šC.]ö{,Cöæ: ž‰hS¯Úã×̶0™v¼:FIŸíò®öãoõÓ»³“GÇjdTDw×ÿ½=DQÒ£ÚöäMšÎpÆd$”‘²‡]Ä«vvclƒ¥Ï[lUg4zÆ£šÙ‰¨f'AÕè~/Íb,p ø±Ì@áí@h 9«O“r˜¥××éàêÝÍÛ»é¨w¯Åþž§ÃUa'€G“,ñmûY ÒU¨z¢áW…#ù±•ýÍ;.w±0â× à>ÖEòÏÒ—,û¦5‚áÐ6êÚ‰…êdG1IgšC¨Ÿ6DЊ¥'7ü¤ÆbýUˆ ÜÆ©·1ñ>;éa½jVsb&ï›áD¼‰Ê ½¦Phõ%çé澎Ê$|˖…$‰¡ëüJà% ©‘”H¨Î–Æ:›ô‡É¯(G¥eÞ*tå“è)fzÅTä§G¼öƒ³>«ŽÔÓbißµ@Û5Dîj½å‰HÒÞ%åî1ž¡™¢ háÉ® ñ› ÷wSÐ/PsYLgÝK&Q8_I–ŒÄ <-†¶ÙXÝÐØ0ŒÃŠIP+‘z^ªKmå,³ñº•DÝm€‰+¥¥­± /j¾²WJI§„¾+/nˆïáì½Éý3<ºß˜BÍé ŽçHð˜ .kª•fž•ÔÿH̬žÁGÅϦÌ »<ÖXï7Ÿê°ÂÿȲLäÜî|Ò‡N¦Ù†öI)0ænG`ø8ÿÁVä2¸}ÿ„‡FÂ~Qµa®ÐÜeTaxù\4h)|ÈܪÌ$YÆQÀªfU/ ‰ù<¨+¦Éw*–™ÀÀ`óÜ-áÖ;¦ í–ñ/s„Bo^2Æ!ºwS2pÀˆÓ@Ý·_ûÛï©(Å8 =CdÄAfëQc1¶£Ip ç"H›îï€ócŒË9Ú$­¢)°ý¾­y ©&gê“FxÒž¯I:P =«S1„"û ›Æù–©gZ«l [ká‚F¸Ûë¶;u»µ„*Df ËÙªã¸v±~!Detc€ÓÀã1,þb”êîÄ· ¢ÆW‘æìºË¤¡0ã^ñ¬C¥oMD‘ïG dp O¿¡#‡Ú0É¡FÂ3&&–§t`Ü%ßÝÆŒñxŸ ü™~ýÍmBá°d¸ßoyw[{ºW'¼nâ7b“àÅI‹ÓåZ'! Mˆ ‚•©}Éá—š÷ÊݽPZ>Õƒêî±R5‹H‰`åÂË€}KxLÇtLÇtLÇtLÇtLÇtLÇtLÿïég¿½² exmh-2.9.0/ftp.expect0000755000170700017070000000100613370473410014022 0ustar valdisvaldis#!/bin/sh # \ exec /usr/bin/expect -f set site [lindex $argv 0] set dir [lindex $argv 1] set theirname [lindex $argv 2] set myname [lindex $argv 3] set password "$env(USER)@" set timeout 60 spawn ftp $site expect "*Name*:*" send "anonymous\r" expect "*Password:*" send "$password\r" expect "*ftp>*" send "binary\r" expect "*ftp>*" send "cd $dir\r" expect "*550*ftp>*" {exit 1} "*250*ftp>*" send "get $theirname $myname\r" expect "*550*ftp>*" {exit 1} "*200*226*ftp>*" close wait send_user "FTP transfer ok\n" exit 0 exmh-2.9.0/exmh.CHANGES0000644000170700017070000067426513370473166014006 0ustar valdisvaldisHISTORY 7/11/2018 valdis.kletnieks@vt.edu Tag and push a 2.9.0 release to clear up the confusion from 6 years of moving code calling itself 2.8.0 cvs repository 04/25/2017 valdis.kletnieks@vt.edu Finally heave 'mhn' over the side. lib/app-defaults lib/editor.tcl lib/extrasInit.tcl lib/mh.tcl lib/msg.tcl lib/partial.tcl lib/sedit.tcl lib/seditExtras.tcl lib/seditMime.tcl lib/partial/{Sedit,custom,guide,mime.attack,reference,software}.html cvs repository 04/24/2017 valdis.kletnieks@vt.edu Add lib/stacktrace.tcl for debugging use cvs repository 04/21/2017 valdis.kletnieks@vt.edu Fix insufficent quoting of parameters to MDNGenerate - blows up if syntactically invalid address is passed in the DSN: header. lib/recipt.tcl cvs repository 04/21/2017 valdis.kletnieks@vt.edu Use version.bash rather than version.csh - who still uses csh for shell scripting? Makefile, version.bash cvs repository 04/21/2017 valdis.kletnieks@vt.edu Proclaim myself emperor exmh.install cvs repository 04/21/2017 valdis.kletnieks@vt.edu Fix gnupg Comment field to dynamically update to the currently running version lib/pgpGpg.tcl cvs repository 04/21/2017 valdis.kletnieks@vt.edu Add skeleton support for nmh 'mhical' and third-party 'gcalcli' to deal with text/calendar mail. lib/mh.tcl, lib/mime.types, lib/calendar.tcl, lib/extrasInit.tcl cvs repository 04/21/2017 valdis.kletnieks@vt.edu Tk/Tcl 8.5 is now a decade old. Heave all pre-8.5 support code over the side. exmh.MASTER, exmh.install, exmh, install.tcl, lib/addr.tcl, lib/main.tcl, lib/mime.tcl, lib/sedit.tcl, lib/utils.tcl cvs repository 16/6/2012 az@debian.org applied patch by Wolfgang Denk to add 'from+to+cc' option to the pick dialog. cvs repository 21/5/2012 az@debian.org fixed receipt.tcl so that content-disposition-notifications work with nmh 1.5. cvs repository 8/5/2012 az@debian.org applied patches by tom lane and kevin cosgrove: improved handling of xhost issues, more robust pgp message parsing cvs repository 04/24/2012 valdis.kletnieks@vt.edu Fix the 'lassign' issue more correctly - Brent Welch suggested how to define one on the fly for pre-tcl8.5. So we bite the bullet and actually use the 8.5 calling sequence. main.tcl, html.tcl, html_formtag.tcl, html_get_http.tcl, html_links.tcl, msgShow.tcl cvs repository 04/22/2012 az@debian.org added two patches from debian: . make audit logging a configurable option . ensure that $HOSTNAME is set in exmhwrapper cvs repository 04/21/2012 welch@panasas.com Update version to 2.8.0 This changes Makefile exmh.install lib/html/exmh.README.html lib/html/index.html lib/html/software.html cvs repository 04/21/2012 welch@panasas.com Added darwin to ps.tcl "SYS V like systems case Added jpilot scripts to misc, contributed by gerhard.siegesmund@epost.de Added Tar.exclude files used for generating tarball releases Fixed MH references in index.html and software.html Added misc/sequence.patch that reflects my local changes to how sequence information is updated in the UI. This is a non-trivial change, and while it is faster, I think there are some lingering corner cases where it isn't perfect. So, I'm just saving the patch and not committing the change to the code. cvs repository 01/23/2012 az@debian.org repaired gnupg cipher option handling cvs repository az az 01/20/2012 az@debian.org repaired date/time parsing in addr.tcl, which kept address db expiration from working properly cvs repository 12/06/2011 valdis.kletnieks@vt.edu lib/pgpMail.tcl - add code to trim trailing blanks before doing PGP signing/encrypting. cvs repository 04/24/2011 az@debian.org consolidated spell checking options: main on sedit pref page, i-spell specific stuff on its own page. i-spell now an explicit choice among spelling programs. updated all related preference doc strings. updated app defaults to include i-spell whole buffer in the more... menu. updated i-spell sedit hook to enable/disable ispell or i-spell depending on spell checker choice. fixed exmh-async integration of custom spell checker: now in line with ispell. cvs repository az 04/21/2011 az@debian.org mime.tcl: fixed documentation of behaviour of mimeFullHeaders exmh.MASTER: fixed tk8.5 font issue. default choice 'fixed' misinterpreted by tk8.5 as a font face, not XLFD...now fixed defined as alias for TkFixedFont, and aliases are consulted first. still somebody will have to extend the font chooser dialog to cover font faces. cvs repository 09/02/2010 az@debian.org lib/msgShow.tcl: applied Harvey Eneman's patch that fixes handling of rfc2369 list-* headers. cvs repository 08/29/2010 az@debian.org implemented quoting of unknown directives when editing text/enriched mails with sedit (this is a fix for debian bug #175193, http://bugs.debian.org/175193) cvs repository 08/26/2010 valdis.kletnieks@vt.edu Finally found the cause of the exmh Log window breaking - we carry our own lassign that had the parameters in opposite order to what base 8.5 code expects, specifically breaking 'clock format' and who knows what else. So rename our lassign to exmh_lassign. lib/html.tcl, lib/html_formtag.tcl, lib/html_get_http.tcl, lib/html_links.tcl lib/msgShow.tcl, lib/utils.tcl cvs repository 08/26/2010 valdis.kletnieks@vt.edu By default, convert blanks to _ in the 'save as' dialog lib/fileselect.tcl cvs repository 08/26/2010 valdis.kletnieks@vt.edu Heave some tcl 7.0-specific code over the side, 7.1 came out in 1993. Is our core code *really* that old? :) exmh-strip.MASTER exmh-bg.MASTER exmh.MASTER cvs repository 06/20/2008 az@debian.org incorporated a number of patches from debian exmh.l: silence some man warnings lib/mh.tcl: mention install-mh by full path in initial greeting lib/bogo.tcl: add learning-from-stdin for learning ham, too (not just spam) lib/glimpse.tcl: add the -W glimpse option (and scope for whole file) to permanent preferences lib/scan.tcl, lib/folder.tcl: fix the stale scan cache problem lib/uri.tcl, html_links.tcl: make html links clickable in inline-displayed html, and consolidate status line handling for links lib/seditExtras.tcl, lib/mime.tcl: patch from Marion Hakanson to fix fd leakage in internal mime qp/base64 decoder patch from debian: add support for recode as alternative to mimencode lib/pgpExec.tcl, lib/pgpGpg.tcl, lib/extrasInit.tcl: added support for gnupg's gpg-agent cvs repository 06/26/2006 valdis.kletnieks@vt.edu lib/html_dpackage.tcl: Skip over blocks we don't know how to interpret anyhow. Thanks to Don Koch for the patch, and Rick Baartman for asking. cvs repository 05/08/2005 valdis.kletnieks@vt.edu exmh.l: debian bug #309891 by way of Alexander Zangerl Fix a bunch of typos cvs repository 4/27/2005 jbeck@eng.sun.com lib/app-defaults-color lib/msgShow.tcl: Added support for marking text between stars (e.g., I *really* mean it) in a bold font. cvs repository 4/27/2005 jbeck@eng.sun.com lib/app-defaults-color lib/msgShow.tcl: Updated regular expressions for Sun bug report highlighting, added support for SpamAssassin report highlighting. cvs repository 4/27/2005 welch@panasas.com lib/bogo.tcl: Added BogoSetup as a trace on bogo(progname) so that preference changes are reflected immediately w/out restarting exmh. cvs repository 4/21/2005 valdis.kletnieks@vt.edu lib/mime.tcl: Add call to FileExistsDialog to prompt before saving a MIME part into an already existing file. cvs repository 4/15/2005 welch@panasas.com channeling Alexander Zangerl lib/bogo.tcl: add the option to give the spam filter a list of message file names on its command line instead of running the filter once on each message as standard input. We know this works for spamassassin, but not sure about the other filters. cvs repository 4/4/2005 welch@panasas.com lib/fileselect.tcl: made use of the built-in tk file dialogs optional. The setting is under the "FS Box" preferences panel. my fingers have grown to know and love the fileselect behavior. lib/fileselect.tcl lib/html_content.tcl lib/main.tcl lib/mime.tcl lib/msg.tcl lib/seditExtras.tcl Restored/updated calls to FSbox (aka fileselect) lib/flist.tcl: fixed FlistUncache to properly clear the global variable in the bg interp lib/mh.tcl: added calls to FlistUncache cvs repository 3/18/2005 welch@panasas.com channeling Alexander Zangerl lib/flist.tcl: Adding FlistUncache to unset flistcache when appropriate lib/folder.tcl: Call FlistUncache when we commit folder changes cvs repository 3/17/2005 welch@panasas.com channeling Alexander Zangerl exmhcomp: support mailto URLs cvs repository 3/4/2005 cwg-exmh@deepeddy.com lib/seqwin.tcl - Make Warp & Narrow work if you aren't already in the folder. cvs repository 3/1/2005 cwg-exmh@deepeddy.com lib/html_content.tcl, lib/main.tcl, lib/mime.tcl, lib/msg.tcl, lib/seditExtras.tcl - Call tk_getOpenDialog or tk_GetSaveDialog instead of FSBox. cvs repository 3/1/2005 cwg-exmh@deepeddy.com lib/main.tcl: Add 'Source' button to log window so I can read in a new source file w/o erasing what's in the command line. cvs repository 3/1/2005 cwg-exmh@deepeddy.com lib/flist.tcl: Run FlistUnseenFoldersInit in the foreground so that it actually works. cvs repository 2/18/2005 cwg-exmh@deepeddy.com lib/ftoc.tcl: Fix patch of 2/3 so it doesn't break if you don't have a detached message window. cvs repository 2/9/2005 valdis.kletnieks@vt.edu lib/mime.tcl: resolve (or at least work around) Debian bug 294212 as a too-zealous splatting of specials broke some content types. I'm adding '.' to the list, but I'm not comfortable adding the full list of rc2045 chars as it includes some shell metachars... cvs repository 2/3/2005 cwg-exmh@deepeddy.com lib/ftoc.tcl: Reset exwin(ftext) whenever the ftext window changes size. cvs repository 1/25/2005 cwg-exmh@deepeddy.com lib/mime.tcl: Special case display of original message in spamassassin processed mail so it doesn't display by default. cvs repository 1/24/2005 welch@panasas.com lib/folder.tcl: fixed the background folder purging script to properly pick up things from the script library cvs repository 1/19/2005 cwg-exmh@deepeddy.com lib/ftoc.tcl: Really fixed bindings for exwin(ftext). cvs repository 1/18/2005 cwg-exmh@deepeddy.com lib/exwin.tcl: Fixed bindings for exwin(ftext). cvs repository 1/17/2005 welch@panasas.com lib/seditExtras.tcl: fixed exmh-async variation of ispell command. lib/seditSel.tcl: fixed exmh-async variation of ispell command cvs repository 1/12/2005 welch@panasas.com lib/uri.tcl: changed use of "file link" back to exec ln lib/quote.tcl: changed use of "file link" back to exec ln exmh-strip.MASTER: eliminated use of [glob ~/.exmh/tk] in the setting of exmh(userLibrary), which we shouldn't need lib/mime.tcl: fix the exec of exmh-strip to be ${argv0}-strip to handle installations with a different base name. Makefile: fixed the ftpdist production cvs tag exmh-2-7-2 cvs repository 1/7/2005 welch@panasas.com lib/exwin.tcl: fixed up lingering focus and position issues with the detached message and ftoc windows. I also trimmed out all the sedit and pref windows from the saved window positions in the case that the window is "stale". lib/msgShow.tcl: added call to Exwin_SeeToplevelMsg in case the user has withdrawn the message display exmh-strip.MASTER: cleared out the Exmh_Debug messages that leak to standard output lib/mime.tcl: added dialog to Save/Extract attachments if the file already exists. exmh.install: changed 2.7.2 date to 1/7/2005 cvs repository 1/6/2005 welch@panasas.com lib/seqwin.tcl: Fixed a buglet that caused the incorrect display (missing the first folder) in the sequences window in some cases. lib/sequences.tcl: removed some erroneous debugging code. once again I forgot that catch will trap a "return", not just errors lib/mh.tcl: minor clean up - changed "catch {set foo}" to "info exists foo" lib/main.tcl: added logging to the startup sequence exmh.install: changed 2.7.2 date to 1/6/2005 cvs repository 1/6/2005 valdis.kletnieks@vt.edu lib/fdisp.tcl - enable scrollwheel support for fdisp canvas cvs repository 1/5/2005 welch@panasas.com lib/folderNew.tcl: folder-protect value wasn't being interpreted as octal when creating new folders. exmh.install: bumped version date cvs repository 1/5/2005 valdis.kletnieks@vt.edu lib/fileselect.tcl, lib/seditExtras.tcl patch from George Ross to not smash filenames when attaching a file to a message, only when saving an attachment cvs repository 1/4/2005 welch@panasas.com exmh-strip.MASTER: Added stub for "winfo" so I could run this with tclsh instead of wish. Updated comments. Made the search for filename hints more aggresive. Added exit if the output file already exists. Added some safety checking on the file name lib/app-defaults: Eliminated " " from the {Save "From" addr} menu entry because it looks like that entry raises errors sometimes. cvs repository 1/4/2005 welch@panasas.com lib/mime.tcl: fixed handling of non-existent attachement save directory cvs repository 1/3/2005 welch@panasas.com lib/html/software.html: updated links cvs repository 1/3/2005 welch@panasas.com added misc/mafe, as contributed by Andrew Billyard which is a perl-tk editor for mh aliases files. cvs repository 1/3/2005 welch@panasas.com Makefile: exmh.README: exmh.install: version.sed: lib/html/index.html lib/html/software.html changed version to 2.7.2 version.csh: Added comments lib/html/exmh.README.html: Added notes about 2.7.2 cvs repository 1/3/2005 welch@panasas.com lib/exwin.tcl: Fixed packing bug for ftoc window that means it didn't match the ftext lines preference setting. cvs repository 1/2/2005 welch@panasas.com lib/app-defaults: added "Save/Extract Attachments" that calls Mime_SaveAttachments. lib/mime.tcl: Added Mime_SaveAttachements that uses exmh-strip to pull an attachment out of an email message. There is a new preference item under "Mime" where you specify the default location for the resulting files. The default is ~/attachments. cvs repository 1/1/2005 welch@panasas.com (for Alexander Zangerl) lib/pgpGpg.tcl: lib/pgpPgp5.tcl: fix of an old pgp problem where recipients were duplicated when pgp is run in interactive mode lib/extrasInit.tcl: a small documentation improvement for the pgp(getextcmd) functionality. faces(xfaceProg) gains a default (uncompface -X) lib/pgpExec.tcl: fix for http://bugs.debian.org/164210: multiple gpg subkeys and passphrases. exmh would not ask for the right passphrase. lib/addr.tcl: ldap options gain defaults that are compatible with debian's openldap config lib/mh.tcl: add Msg-Protect and Folder-Protect to the default .mh_profile that is generated when setting up new users. (These changes are inspired by a patch from Alexander, but not the same) lib/inc.tcl: use $install(dir,bin) to specify an absolute path to the inc.expect script lib/seditExtras.tcl: use $install(dir,bin) to specify an absolute path to the exmh-async script lib/mime.tcl: use $install(dir,bin) to specify an absolute path to the ftp.expect script. Also changed MimeMakeBoundary to use [clock seconds] instead of re-writing the output of [exec date]. cvs repository 12/31/2004 welch@panasas.com lib/exwin.tcl: removed code that explicitly set ftoc and msg window heights that had been added as part of the detatched msg and ftoc changes. This isn't necessary and causes misinterpretation of the preferences ftoc lines value. (reportedly, this change doesn't fix anything.) cvs repository 12/29/2004 welch@panasas.com lib/mh.tcl: Optimized MhReadSeq to not loop through the mhPriv array in Tcl, but instead use the array command's ability to work on subsets of an array by using patters. This really speeds up Flist. NOTE: THIS DEPENDS ON A TCL 8.3 FEATURE FOR THE "array unset" COMMAND lib/flag.tcl: cleaned out some Exmh_Debug calls lib/folder.tcl: removed unnecessary calls to Seq_Msgs for sequences listed in the sequences resource. I can't figure out what good that was supposed to do. lib/sequences.tcl: Replaced Seq_Trace with SeqCount, and call it explicitly instead of from a trace. lib/seqwin.tcl: added error checking because it gets called earlier than before because of the explicit SeqCount calls lib/seditExtras.tcl: Also allow for "7bit" and "8bit" encodings. lib/utils.tcl: FileDelete adds a log message now cvs repository 10/18/2004 welch@panasas.com lib/seditExtras.tcl: patch from George Ross to fix attachments of plain files with no encoding. cvs repository 10/11/2004 welch@panasas.com lib/mime.tcl: lib/seditExtras.tcl exmh-strip.MASTER: added ability to use mimencode if it exists, because it is much faster than using the Tcl versions. We should also figure out how to use mhstore. lib/seditQP.tcl: minor edits lib/background.tcl: added better debugging for when the background process gets errors from commands shipped to the front end. lib/flist.tcl: restored the flistcache removed on 9/10 because the impact was substantial. There is still a buglet in there where the right sequence of message views, deletes, and arrivals can fool the cache. I think the correct thing is to special case the current folder, but I haven't done that yet. lib/inc.tcl: Introduced the use of Mh_FolderFast to set the current folder because "exec folder +foo" turns out to readdir() the entire folder, which can be a bit slow on horrendously large directories. lib/mh.tcl: fixed Mh_SetContext cvs repository 10/08/2004 valdis.kletnieks@vt.edu lib/base64.tcl - properly deal with trailing '=' so we don't append spurious nulls to the file cvs repository 10/08/2004 valdis.kletnieks@vt.edu lib/seditExtras.tcl - add fconfigure -translation binary so base64 encoding works properly. cvs repository 09/10/2004 welch@panasas.com lib/flist.tcl: removed the flistcache as inspired by Harvey Eneman and Jongki Suwandi. This cache caused message highlighting to not occur in some cases. lib/mh.tcl: patch from Harvey Eneman to fix the problem where Mh_Sequences does not clear the in-memory sequence state if a sequence file no longer exists. cvs repository 08/23/2004 welch@panasas.com lib/base64.tcl: fix two bugs, one with perfectly aligned blocks where there was an "undefined result" error. The other was that lines were not properly split at 72 chars. lib/mime.tcl: properly set binary encoding on decoded files. cvs repository 08/07/2004 valdis.kletnieks@vt.edu lib/app-defaults, lib/editor.tcl, lib/extrasInit.tcl, lib/mh.tcl, lib/sedit.tcl, lib/mh.tcl, lib/html/DSN-MDN.html, misc/README.nmh-dsn Oldie but goodie - merge in patch from Martin Hamilton to allow setting RFC3461 DSN options (originally against 1.6.5). Requires a patched mh/nmh (I forwarded the nmh guys a patch for nmh 1.1rc3 and put a patch for nmh 1.0.4 in misc/ for good measure). cvs repository 07/29/2004 welch@panasas.com lib/bogo.tcl - added Exmh_Status to Bogo_Filter because they take a while cvs repository 07/28/2004 welch@panasas.com lib/bogo.tcl - added catch around sa-learn pipe, as that can raise errors if sa-learn generates error output. lib/app-defaults - Added new key bindings Bogo_Filter spam Bogo_Filter ham lib/html_images.tcl lib/html.tcl - added preference to disable image display in a list of folder patterns. Contributed by Jürgen Vollmer lib/sequences.tcl - changed default for seqwin(show) to "unseen" from "cur" cvs repository 07/28/2004 valdis.kletnieks@vt.edu Clean up 2 bugs from the 07/26 'exec' hunt... lib/preferences.tcl - remove extraneous -p flag on 'file mkdir' lib/urlFace.tcl - missed an 'exec' call better done with regsub. cvs repository 07/26/2004 welch@panasas.com exmh-strip.MASTER: removed use of mime(encode) exmh.install: set version to 2.7.1 install.tcl: removed old unused global statement lib/base64.tcl: chopped Base64_Encode into three parts, Base64_EncodeInit, Base64_EncodeBlock, Base64_EncodeTail so it can be used more flexibly as a replacement for mimencode Changed Base64_Decode to tolerate and ignore newlines lib/exwin.tcl: got the non-detached window case to work for me. lib/main.tcl: changed the exmhDebug default to 0 because I was getting massive console spew lib/mime.tcl: removed use of mime(encode) lib/seditExtras.tcl: removed use of mime(encode). If you are a heavy user of the Quote feature in Sedit, you should check this as there is an auto-detect of quoted-printable in here that I support, but cannot see how it is ever reached. lib/seditQP.tcl: removed use of mime(encode) cvs repository 07/26/2004 welch@panasas.com lib/pick.tcl: Applied patch from Bruce Mah to search over sender or mailing-list headers lib/seqin.tcl: Applied patch from Axel Belinfante to be able to have sequences that are always shown, and those that are never shown. lib/sequences.tcl: Added preference for sequences to always show lib/utils.tcl Moved Axel's "mylsearch" into utils.tcl as "patsearch" cvs repository 07/26/2004 valdis.kletnieks@vt.edu catch CVS up to a weekend's worth of concentrated coding... Bayesian filter stuff... lib/bogo.tcl - Add support for spamassassin's sa-learn program lib/app-defaults - Add a menu for bogo.tcl calls, as the stuff in misc/README.mybogo.html is woefully out of date - in fact, it didn't handle a "range" of messages at all. The grey-out code for the Spam... menu is wonky - it *should* grey out if $bogo(inUse) is false, but that's too complicated for 3AM coding. Also, you can't learn a folder unless you first select a message. Adding key-S and key-H bindings also not done... If anybody cares enough, feel free to fix/improve/add it... :) lib/html/software.html - Mention spamassassin as an optional package lib/html/custom.html - Document the Preferences pane for bogo.tcl, and sort the list to match the actual display order of the entries. A few small clean-ups.. Doc fixups.. lib/html/exmh.README.html - fix a typo in Anders Klement's name, and cleaned up some broken HTML links/etc and outdated info (like an AIX 3.2 bug - if anybody's trying to install exmh on a 3.2 system, that's the least of their worries...) lib/report.tcl - DTRT if user has a personalized 'components' file, or a 'comp: -form some.other.comps' MH profile.. (very important if they have stuff like a From: header needed to make the mail actually usable...) lib/folder.tcl - Change a /tmp to [Env_Tmp] to stop races lib/utils.tcl - remove pre-TCL 8.0 code from File_Delete lib/mh.tcl - remove ancient tk4.2 code from Mh_Rename lib/folder.tcl, lib/glimpse.tcl, lib/pgpWWW.tcl, lib/scan.tcl, lib/seditExtras.tcl, lib/seditSel.tcl, lib/tioga.tcl, lib/urlFace.tcl, lib/folderNew.tcl, lib/getnews.tcl, lib/glimpse.tcl, lib/html_content.tcl, lib/html_cache.tcl, lib/html_images.tcl, lib/inc.tcl, lib/mime.tcl, lib/mh.tcl, lib/quote.tcl, lib/pgpMain.tcl, lib/preferences.tcl, lib/uri.tcl - replace 'exec chmod' with 'file attributes -permissions' replace 'exec mkdir' with 'file mkdir', 'exec ln' with 'file link', 'exec mv' with 'file rename', most 'exec cp' with 'file copy', 'exec rmdir' with 'file delete', mass change of 'exec rm' to either File_Delete or [file delete -force' cvs repository 07/18/2004 valdis.kletnieks@vt.edu lib/fileselect.tcl - Be more anal-retentive in what default names we will accept. Alphanumeric, period, hyphen, underscore only. Also, we trim off leading dots, just in case the user isn't paying attention... cvs repository 07/18/2004 valdis.kletnieks@vt.edu lib/mime.tcl - Same mail as below fix triggered another buglet - we should *always* prefer a rfc2183 Content-Disposition: filename= over a name= off the Content-Type: header. The code as written was dependent on what order we saw the MIME headers (blech!). While there, I also added a few filtering regsub calls... cvs repository 07/18/2004 valdis.kletnieks@vt.edu lib/mime.tcl - fix MimeSetDisplayFlag to properly implement rfc2183 Content-Disposition: precidence. Bug found when I got a image/jpeg with a 'C-Disposition: attachment' and it displayed anyhow. cvs repository 07/02/2004 valdis.kletnieks@vt.edu lib/exwin.tcl - first cut at separable ftoc and msg panes cvs repository 06/18/2004 welch@panasas.com Updating version to 2.7.0 in preparation for a release cvs repository 06/14/2004 welch@panasas.com mh.tcl: Slight tweak to version detection to make it more robust. bogo.tcl: moved misc/mybogo.tcl to lib/bogo.tcl - this is a wrapper around spamassasin or other spam filters lib/app-defaults-mono: removed "blue" from the monochrome Xdefaults app-defaults: added file magic strings for PDF documents force the frame padding to 0 because it is non-zero in 8.4 cvs repository 05/22/2004 cwg-exmh@deepeddy.com exmhwrapper - Prepend the hostname if we're running on the local host. This allows bifffolder to work even if it's on a different machine. cvs repository 05/11/2004 cwg-exmh@deepeddy.com mime.tcl - Don't display part inline by default if its disposition is "attachment". cvs repository 09/29/2003 cwg-exmh@deepeddy.com quote.tcl - In Quote_MultipartDefault, bulletproof against undefined numParts defaulting to zero. cvs repository 08/28/2003 cwg-exmh@deepeddy.com ftoc.tcl - In FtocCommit, clear all unseen messages at the same time. (modification of the 7/13 change) cvs repository 07/13/2003 welch@acm.org ftoc.tcl: patch from Louis Mamakos to batch up the sequence updates when doing large deletes. cvs repository 07/11/2003 welch@acm.org inc.tcl: patch from Glenn Burkhardt to add -user to inc command cvs repository 06/11/2003 haldevore@acm.org Modified misc/mybogo.tcl to save and restore target cvs repository 06/11/2003 haldevore@acm.org Added code, and a README for Patrick Carr's Bogofilter stuff to misc directory cvs repository 06/11/2003 haldevore@acm.org Added code, manpage, and a README for Justin Mason's mhthread to misc directory cvs repository 06/11/2003 haldevore@acm.org patch from "Klaus Elsbernd" mh.tcl It clears the mhPriv(otherpriv) variable, which otherwise grows infinitly, when reading .exmhcontext-File multiple times and writing it afterwards. cvs repository 06/01/2003 welch@panasas.com mime.tcl - add skipping of blank lines to help find the start of PGP messages better. Based on fix by Joel Hatton cvs repository 05/19/2003 welch@panasas.com pgpPgp65.tcl - Added +compatible=off to batchmode flags (Neil Rickert) added version check improvement for PGP 6.5 (Neil Rickert) (added . - and _ to the pattern, too (kre)) preferences.tcl - In the toplevel display, changed row of unsorted buttons to a sorted listbox cvs repository 04/21/2003 valdis.kletnieks@vt.edu pgpMain.tcl - I can't type, fix elsif to elseif cvs repository 04/21/2003 valdis.kletnieks@vt.edu patch from Kevin Oberman lib/pgpMain.tcl - add tweak to support Mutt-generated pgp-sign messages cvs repository 04/08/2003 haldevore@acm.org patch from Chris Garrigues thread.tcl Fix to prevent threading from erasing unseen sequence cvs repository 04/04/2003 welch@panasas.com sequences.tcl - removed Exmh_Debug from Seq_Trace fcache.tcl - removed Exmh_Debug flag.tcl - restored variable trace on flist(totalCount,unseen) exmh.install - bumped date on the release cvs repository 04/03/2003 haldevore@acm.org patch from Klaus Elsbernd elsbernd@dfki.uni-kl.de mh.tcl fix variable usage in sequences, corrects a problem with private sequences cvs repository 04/03/2003 haldevore@acm.org select.tcl patch from Robert Elz (kre@munnari.OZ.AU) select.tcl - Thorough input validation when selecting message by keying message number cvs repostiory 4/2/2003 welch@panasas.com flist.tcl, sequences.tcl - Repaired the change made on 4/1 cvs repository 04/02/2003 valdis.kletnieks@vt.edu exmh.MASTER, lib/widgets.tcl - set a default cursor of 'left_ptr' (otherwise enlightenment 0.16.5 doesn't play nice with XFree86 4.3.0 cursors) cvs repository 04/02/2003 haldevore@acm.org flist.tcl - Only call Fcache_Redisplay if folders being cached cvs repostiory 4/1/2003 welch@panasas.com flist.tcl, sequences.tcl - Fix to call Fcache_Redisplay from the trace on flist. cvs repository 04/01/2003 haldevore@acm.org Multiple fixes from Robert Elz (kre@munnari.OZ.AU) select.tcl, html/guide.html - Select message by typing now allows "s" to show the message or "-" to go to the prior message mh.tcl - Ignore garbage in sequence files main.tcl - Add Disable/Enable button to debug log window extrasInit.tcl, sedit.tcl, seditMime.tcl - add preference item to make insertion of x-mailer header optional and check the item (applicable to Sedit only) cvs repository 03/31/2003 haldevore@acm.org select.tcl, removed fix for non-numeric typing cvs repostiory 3/30/2003 welch@panasas.com sequences.tcl, flist.tcl, main.tcl, exmh-bg.MASTER - restructure sequence searching so it is done in the background process like it used to be in exmh-2.5 select.tcl - fixed non-numeric typeing mh.tcl - added stubs for 2.5 APIs Mh_MarkSeen and Mh_MarkUnseen app-defaults - removed hardwired "unseen" exmh.install, etc, changed version to 2.6.3 cvs repository 03/26/2003 haldevore@acm.org flag.tcl - Applied patch sent to exmh-users by dglo@ssec.wisc.edu 2.6.2 Tarball created 3/21, uploaded 3/25 exmh-2-6-2 CVS tag cvs repository 03/21/2003 welch@panasas.com scan.tcl - Added -noheader to the scan invocation. ftoc.tcl - protected against unfound message in Ftoc_MoveFeedback, although I'm unsure how this error could have come up. cvs repository 03/20/2003 haldevore@acm.org html/reference.html - Expand description of Sequences... menu cvs repository 03/18/2003 haldevore@acm.org msgShow.tcl - change MsgShowListHeaders to keep all protocols and include the protocol in the menu item. This should be made smarter or prettier someday. addr.tcl - add escaped quotes around search expression so it survives as a single argument after the eval. cvs repository 03/18/2003 valdis.kletnieks@vt.edu msgShow.tcl - Fix MsgShowListHeaders to be pedantically correct - it had been accidentally picking the first field only. It now loops through each field and only saves http, https, and mailto URIs. cvs repository 03/18/2003 welch@panasas.coM exmh.install - bumped up date for 2.6.2 msgShow.tcl - added \n adn \t to the white-space removal in the Hook_MsgShowListHeaders proc. cvs repository 03/15/2003 valdis.kletnieks@vt.edu seqwin.tcl - bug fix for brent's previous bug fix. Make sure that $seqwin(startuphidden) is set before we call SeqWinToggle cvs repository 03/14/2003 welch@panasas.com sequences.tcl, seqwin.tcl - Bug fixes for previous submit bindings.tcl - fixed this to properly allow users to override bindings. This is an ancient bug! cvs repository 03/12/2003 welch@panasas.com sequences.tcl, seqwin.tcl - Delay the initial display of the sequences window. cvs repository 03/12/2003 valdis.kletnieks@vt.edu fcache.tcl - Fix problem with fcache listing. The rows would be packed to fit 'folder' and then expanded with 'folder:NNN' for unseen msgs, which could cause it to wrap to a next line, leaving you with (for example) two rows and an orphan on a 3rd row. cvs repository 03/11/2003 welch@panasas.com flag.tcl - Removed trace on flist(totalcount,$mhProfile(unseen-sequence)) and replaced with explicit call to Flag_Trace in Flist_Done. This is to reduce the amount of variable trace firing and speed things up a bit. flist.tcl - Removed some ancient debugging code that was an ancient ancestor of the unseen/sequences window. folder.tcl - Shifted the Ftoc_ShowSequences call to eliminate one extra redisplay. ftoc.tcl - added various debugging and fixes to Ftoc_FindMsg, but the trouble was really caused by a -header flag in a users .mh_profile for scan. mime.tcl - fixed the MimeHeaderSort procedure to use the patterns in Folder-Display and Folder-Surpress correctly, and to work better with non-defaults (Tom Lane's fix) seqwin.tcl - eliminated one update idletasks to eliminate screen updates. cvs repository 02/21/2003 welch@panasas.com ftoc.tcl - Reverted change to the binary search in Ftoc_FindMsg because the new method sometime causes stack traces because the nextlineno computation returns values out of range. mh.tcl - added call to Mh_SequenceUpdate to Mh_SetCur seq.tcl - removed Mh_SequenceUpdate call from Seq_Set, because that procedure is usually called with the results of Mh_Sequence, so we were reading sequence information and then immediately writing it back out. Also removed "unseen" from the seqAlwaysShow preference item. Otherwise you couldn't clear that setting because of the way preference defaults works. seqwin.tcl - fixed stack trace by adding initialization for seqwin(folders,$seq) cvs repository 02/20/2003 welch@panasas.com folder.tcl - fixed Folder_IsShared parameter definition that conflicted with global variable. cvs repository 02/19/2003 welch@panasas.com flist.tcl - fixed the Flist button, which was broken by the flistcache Also fixed the autoSort feature in Flist_UpdateUnseen cvs repository 02/18/2003 welch@panasas.com flist.tcl, folder.tcl - oops! botched change related to Flist_UpdateUnseen described below. Repackaged 2.6.1 and updated cvs tag. cvs repository 02/18/2003 welch@panasas.com Makefile, exmh.README, exmh.install, version.sed, exmh.README.html, index.html, software.html 2.6.1 release cvs tag exmh-2-6-1 cvs repository 02/18/2003 welch@panasas.com mime.tcl - MimeHeaderSort fix from Tom Lane so that it displays headers that appear in Header-Display first, before unsuppressed ones. folder.tcl - Eliminated call to Flist_UpdateUnseen from FolderChange, which does a little too much. This means that exmh now keeps track of the "unvisited folders" better for Ftoc_NextFolder ('F' binding) html.tcl - added Http_stop call to Html_Stop app-defaults-color - changed unseen sequence back to having a blue foreground. mime.types - added "pps" for application/powerpoint cvs repository 02/17/2003 welch@panasas.com extrasInit.tcl, pgp.tcl - picked up pgp(extpass) patch from Alexander Zangerl flist.tcl - FlistFindSeqsInner added check to eliminate calls to Seq_Set if the sequence information for a folder hasn't changed ftoc.tcl - Changed msgtolinecache and linetomsgcache so that they have no entries for empty ({}) mappings. I was running into a mapping for the last text widget line that didn't contain a message and ended up messing up incremental folder scans Ftoc_MsgNumber doesn't cache anything if there is no mapping Retrieved FtocShowUnseen from exmh-2.5 and use that for the unseen sequence instead of the more general search main.tcl - a slight varition on the fix that slipcon made to the millisecond time stamps. mh.tcl - rooted out an "array unset" that doesn't work in Tcl 8.0 thread.tcl - fixed call to Flist_ForgetSequence (changed to Seq_Forget) Minor HTML cleanup, including pointer to the Wiki. I added comments to several files that identify old exmh APIs, including flist.tcl, folder.tcl, mh.tcl, msg.tcl, cvs repository 02/16/2003 cwg-exmh@deepeddy.com msg.tcl - Only call Ftoc_ShowSequence in MsgChange if we have a valid message. ftoc.tcl - Bulletproof Ftoc_ShowSequence cvs repository 02/10/2003 valdis.kletnieks@vt.edu exmh-strip.MASTER, lib/aliases.tcl, lib/background.tcl, lib/busy.tcl lib/buttons.tcl, lib/editor.tcl, lib/exwin.tcl, lib/faces.tcl lib/flist.tcl, lib/folder.tcl, lib/getnews.tcl, lib/glimpse.tcl lib/inc.tcl, lib/mh.tcl lib/mime.tcl lib/seqwin.tcl Add greppable text to Exmh_Debug call cvs repository 02/10/2003 valdis.kletnieks@vt.edu lib/fcache.tcl - Put in John Beck's fix for extraneous 'folder:0' in the fdisp cvs repository 02/10/2003 cwg-exmh@deepeddy.com scan.tcl - fix lineVar and line references to linenoVar and lineno. cvs repository 02/09/2003 welch@panasas.com Making the 2.6 release, cvs tag exmh-2-6 These files were updated: COPYRIGHT Makefile exmh.CHANGES exmh.README exmh.install version.sed lib/html/exmh.README.html lib/html/index.html lib/html/software.html In addition, this tar file of handy scrips was uncommited in my misc dir. misc/mhutils.tar.gz cvs repository 02/09/2003 welch@panasas.com main.tcl - added microsecond granularity time stamps to log messages msg.tcl - added Msg_ShowCurrent compatibility routine cvs repository 02/07/2003 cwg-exmh@deepeddy.com folder.tcl, ftoc,tcl, scan.tcl - Call Ftoc_ShowSequences in Ftoc_Update on the new messages. Cal Ftoc_ShowSequences in FolderChange. Don't call Ftoc_ShowSequences in ScanFolder and Scan_Inc. This both cuts down on the number of lines we call Ftoc_ShowSequences on and eliminates a timing window that was generating "Cannot find $msgid ($minmsgid,$maxmsgid)" warnings. cvs repository 11/07/2002 valdis.kletnieks@vt.edu mh.tcl, flist.tcl, tclIndex - add new function MhGetSeqCache to speed up flist/sequence handling. We now only call MhReadSeqs once per folder, and skip over sequences listing in $seqwin(nevershow). Also, migrate some code into new function FlistFindSeqsInner so that it can be called with BgRPC to make exmh-bg happier. cvs repository 11/1/2002 cwg-exmh@deepeddy.com seqwin.tcl - prepend sequence names with "pane" when using to name panes because a pane can't start with a Capital letter. cvs repository 10/30/2002 cwg-exmh@deepeddy.com mh.tcl - When compacting sequences, don't compact if it's already compacted. cvs repository 10/29/2002 cwg-exmh@deepeddy.com msg.tcl - In Msg_Show, if there are no messages in the sequence we're trying to show, then show 'cur'. sequences.tcl - Minor cleanups in Seq_Trace and improvements to debug code. flist.tcl - in FlistResetVars, sort array names so that totalcount gets cleared after seqcount in order to keep it from going negative. mh.tcl - When rewriting the sequences file, don't expand the other sequences. cvs repository 10/28/2002 cwg-exmh@deepeddy.com msg.tcl, editor.tcl, folder.tcl, ftoc.tcl, main.tcl, mh.tcl, sequences.tcl, thread.tcl - Remove message checkpoint code which was originally intended to work around an mh mark bug, but which now seems unneeded and needlessly complex (causing messages to not get unmarked in various contexts). cvs repository 10/16/2002 haldevore@acm.org pick.tcl - Adaptation of Ted Cabeen's "catch up to current" code cvs repository 09/23/2002 cwg-exmh@deepeddy.com mh.tcl - some bulletproofing in MhReadSeqs. cvs repository 09/21/2002 cwg-exmh@deepeddy.com ftoc.tcl, msg.tcl, pick.tcl, scan.tcl, thread.tcl - Remove the $folder argument from Ftoc_ShowSequences and Ftoc_Update because it's always the current folder; break Ftoc_ShowSequence out of Ftoc_ShowSequences; add an optional argument to both procedures that specifies the particular message ids to show; and change most calls to Ftoc_ShowSequences to call Ftoc_ShowSequence or to specify the optional argument or both. cvs repository 09/09/2002 Robert Elz via welch@panasas.com ftoc.tcl - Fixed reference to $L cvs repository 08/26/2002 Robert Elz via cwg-exmh@deepeddy.com pick.tcl - change the order of the arguments to pick to get around nmh bug. cvs repository 08/23/2002 cwg-exmh@deepeddy.com Intro.html, Search.html, custom.html, exmh.README.html, guide.html, overview.html, reference.html, tutorial.html - Documentation updates for all my recent patches. cvs repository 08/22/2002 cwg-exmh@deepeddy.com mh.tcl - Cache sequences so we don't read the .sequences files over and over and over. seqwin.tcl, sequences.tcl - New preferences item for orientation of sequences panes. seqwin.tcl - Fix "Hide When Empty" and possibly "Icon Window". sequences.tcl - Speed up Seq_Del. pick.tcl - Redisplay sequences at the end of PickMarkSeen. msg.tcl - Don't use Ftoc_MsgIterate in Msg_Mark and Msg_UnMark. cvs repository 08/21/2002 cwg-exmh@deepeddy.com flag.tcl - Don't die in Flag_MsgSeen if flist(totalcount,unseen) is undefined. app-defaults - Msg_MarkUnseen is now {Msg_Mark unseen}. msg.tcl - left a $ off of $mhProfile(unseen-sequence) ftoc.tcl - Needed quotes around argument to Exmh_Status. cvs repository 08/20/2002 cwg-exmh@deepeddy.com app-defaults-color - Change default colors of ftoc so highlighted sequences will appear better. seqwin.tcl - New File; Replacement for unseenwin...more generalized. sequences.tcl - seqwin hooks are in here. flist.tcl - Initialize flist() elements differently; Flist_FindUnseen is now Flist_FindSeqs and calls Seq_Set instead of doing it by hand. ftoc.tcl - Ftoc_FindMsgs replaces Ftoc_FindMsg and handles lists of messages; Ftoc_MsgNumbers replaces Ftoc_MsgNumber and handles lists of lines; ftoc_NewFtoc now takes an optional argument to specify the lines; defaulting again to ftoc(lineset); remove Ftoc_MarkSeen as dead code; New function Ftoc_CurLines and rewrite Ftoc_Iterate to use Ftoc_CurLines; new function Ftoc_MsgIterate to use instead of Ftoc_Iterate in several places; call Msg_Show instead of Msg_ShowCurrent and Msg_ShowUnseen; call Seq_Del and Seq_Add instead of Mh_SequenceUpdate or Seq_RemoveMsg mh.tcl - Call Seq_Add and Seq_Del instead of Mh_SequenceUpdate; Seq_Expand moved back here and named back to MhSeqExpand; Seq_Modify rewritten, moved back here and named back to MhSeq. msg.tcl - Merge Msg_ShowCurrent and Msg_ShowUnseen into Msg_Show; Call Ftoc_MsgNumbers instead of Ftoc_MsgNumber; Call Ftoc_FindMsgs instead of Ftoc_FindMsg; Call Seq_Add or Seq_Del instead of Seq_RemoveMsg or Mh_SequenceUpdate; Call Ftoc_MsgNumbers or Ftoc_MsgIterate where it's simpler than Ftoc_Iterate; app-defaults, background.tcl, inc.tcl, pgpWWW.tcl, user.tcl - Use Flist_FindSeqs instead of Flist_FindUnseen. bindings.tcl, folder.tcl, inc.tcl - Msg_ShowCurrent and Msg_ShowUnseen are now Msg_Show. editor.tcl - use new Ftoc_FindMsgs instead of Ftoc_FindMsg pick.tcl - use Seq_Del instead of Seq_RemoveMsg. print.tcl - Use Ftoc_MsgIterate instead of Ftoc_Iterate. scan.tcl - Use Ftoc_MsgNumbers instead of Ftoc_MsgNumber; call Ftoc_ClearMsgCache and Ftoc_ShowSequences in Scan_ProjectSelection. thread.tcl - Use Ftoc_MsgNumbers instead of Ftoc_MsgNumber; Ftoc_FindMsgs instead of Ftoc_FindMsg bindings.tcl, fcache.tcl, flag.tcl, flist.tcl - use $mhProfile(unseen-sequence) instead of hard coding 'unseen'. extrasInit - remove UnseenWin initialization; change topten reference to unseenWin to be to seqWin instead. cvs repository 08/08/2002 cwg-exmh@deepeddy.com sequences.tcl, flag.tcl - move flag handling from Seq_Trace into new Flag_Trace. sequences.tcl - code cleanup. flist.tcl - Don't unset totalcount, it breaks Flag_Trace; set to zero instead. cvs repository 08/06/2002 cwg-exmh@deepeddy.com folder.tcl - Mark display valid when we change folders. unseenwin.tcl - Change folder if the display isn't valid. cvs repository 08/06/2002 cwg-exmh@deepeddy.com app-defaults, fcache.tcl, flag.tcl, flist.tcl, ftoc.tcl, inc.tcl, main.tcl, mh.tcl, msg.tcl, pick.tcl, scan.tcl, sequences.tcl thread.tcl, unseenwin.tcl - 1) Renamed flist(new,???) to flist(seqcount,???,unseen), flist(newseq,???) to flist(seq,???,unseen), and flist(newMsgs) to flist(totalcount,unseen) and generalized many of the functions which referred to them to have a sequence argument. 2) Reorganized sequences code into its own file from mh.tcl and flist.tcl; involved renaming of functions which is why so many files are touched in this patch. 3) As a result of the above two items merged Mh_Sequence and Flist_UnseenMsgs, which once generalized did almost exactly the same thing into the single funciton Seq_Msgs. 4) Did most of the prep-work for generalization of the unseen window to be a general sequences window so that now all the needed data is tracked. The next step will be to use that data. cvs repository 08/03/2002 cwg-exmh@deepeddy.com unseenwin.tcl - Reindent all code to be more standard. I was having a problem with emacs reindenting this as I worked on it and making it hard to tell my real changes from the indents, so I'm formatting the baseline more "correctly" so that "cvs diff" can be useful. cvs repository 07/25/2002 welch@panasas.com lib/app-defaults-color: added "urgent" sequence so it shows up in the Sequences menu. It has -foreground purple by default. lib/exwin.tcl: added "raise" to Exwin_Toplevel so that hidden windows have a better chance of coming to the top when they are opened. lib/inc.tcl: sort the MyIncTmp directory before processing so that messages get ordered date correctly after filtering. lib/mh.tcl: fixes to turn of regexp special characters from folder names - contributed by John Farrell lib/mime.tcl: lib/uri.tcl: Added way to display defered HTML inside exmh. Contributed by Tomas Gradin lib/msg.tcl: Added Msg_Mark and Msg_UnMark, but these are not used. Thought I needed them for Sequence support, but the Sequences... menu already works without them. lib/seditBind.tcl: Moved the SeditBeautify binding to the correct bindtag so it doesn't fire on the main message window. lib/widgets.tcl: Added catch inside Widget_ReEvalCmd cvs repository 07/26/2002 cwg-exmh@deepeddy.com folder.tcl - Call Msg_Change with skipdisplay in Folder_Pack too. cvs repository 07/26/2002 cwg-exmh@deepeddy.com scan.tcl,ftoc.tcl - Found the bug in ftoc.tcl which was causing the current message to get lost. cvs repository 07/25/2002 cwg-exmh@deepeddy.com flist.tcl - New proc Flist_SetUnseen which can be called instead of Flist_AddUnseen to avoid calling Flist_ForgetUnseen. Call it in Flist_UnseenMsgs. Also remove some ancient dead code from the end of Flist_AddUnseen. folder.tcl, flist.tcl - Move ftoc(autoSort) test from FolderChange to Flist_UnseenUpdate so that it will be called more in more cases. msg.tcl, folder.tcl - Add new possible value for second value to Msg_Change of "skipdisplay" which says to not change the message display when changing messages; then use this value in Folder_Sort so sorts don't cause the message display to rescroll to the top. This makes them much less anoying; pretty important if it gets called automatically by background processing. scan.tcl - In Scan_FolderForce, call Flist_UnseenMsgs instead of Flist_ForgetUnseen so that the folder doesn't move in the unseen window; also call Ftoc_Change because the current message can get lost somehow. cvs repository 07/22/2002 cwg-exmh@deepeddy.com scan.tcl - In ScanFolder, don't try to scan for only new messages if ftoc(numMsgs) is zero. cvs repository 07/22/2002 cwg-exmh@deepeddy.com ftoc.tcl, msg,tcl, scan.tcl - Eliminate optional "line" argument to Ftoc_FindMsg, not incidently removing *all* the code that between the old location and the new location in my patch of 7/19; as a result, also remove the optional line argument to Ftoc_Change and the msgid argument to Msg_Change; also, of course, change all the callers of these functions, and remove the dead Msg_ShowWhat proc. This gives us a net reduction in code and makes it all somewhat clearer. Let's see what I broke by doing this. pgpMain.tcl, pgpOld.Tcl - Call Msg_Change, not MsgChange. cvs repository 07/19/2002 cwg-exmh@deepeddy.com ftoc.tcl - In Ftoc_FindMsg, move the cache check until after the processing of $line. cvs repository 07/18/2002 cwg-exmh@deepeddy.com scan.tcl - Don't clear the "+" from cur. cvs repository 07/15/2002 valdis.kletnieks@vt.edu pgpExec.tcl - multiple fixes. Added a second call to CheckSuccess to both Exec_Encrypt and Exec_EncryptSign (and a 'file delete' to clean up beforehand) so we actually *fail* if the second try doesn't work. Also, fixed the regexp in CheckSuccess - it failed to deal with multiple lines of output, and I added gnupg 1.0.7 support. cvs repository 07/15/2002 cwg-exmh@deepeddy.com flist.tcl - in Flist_UnseenUpdate, don't push the folder onto the unvisited list if it's the current folder. cvs repository 07/15/2002 cwg-exmh@deepeddy.com folder.tcl - Gratitiously change the name of the 'f' variable wherever it's used either to 'folder' or to 'file' to be more consistent with other code. cvs repository 07/13/2002 cwg-exmh@deepeddy.com flist.tcl,folder.tcl - Completely back out the fixpacksort patch from two years ago that hal installed because of the unseenwindow shuffling that occurs and besides the Flist_ForgetUnseen proc is supposed to handle this case. If there is indeed a problem that occurs, we can fix it in a way that won't shuffle the unseen window. cvs repository 07/12/2002 cwg-exmh@deepeddy.com flist.tcl - Remove call to Flist_ResetUnseen in Flist_UnseenUpdate so that the unseen window won't get shuffled all the time. cvs repository 07/12/2002 cwg-exmh@deepeddy.com scan.tcl - Back out the removal of Ftoc_Reset from 7/3/2002 as well as yesterday's attempt to fix some of the problems caused by that bad idea. cvs repository 07/11/2002 cwg-exmh@deepeddy.com scan.tcl - in ScanFolder, we don't know what the last message is yet, so we need to use Widget_Text_End instead. Also, call Ftoc_RescanLine if need be. cvs repository 07/10/2002 cwg-exmh@deepeddy.com ftoc.tcl - In Ftoc_ClearCurrent, if ftoc(curLine) isn't set use Mh_Cur to find where we're clearing. cvs repository 07/03/2002 cwg-exmh@deepeddy.com folder.tcl, ftoc.tcl - Don't call Scan_Folder in FolderChange; properly initialize ftoc(displayValid) to 1 so that Scan_Folder will be called when needed. cvs repository 07/03/2002 cwg-exmh@deepeddy.com scan.tcl - Remove unnecessary call to Ftoc_Reset in ScanFolder cvs repository 07/02/2002 cwg-exmh@deepeddy.com folder.tcl - Call Flist_UnseenUpdate just before calling Scan_Folder in FolderChange cvs repository 07/02/2002 cwg-exmh@deepeddy.com scan.tcl - Remove bogus call to Flist_ForgetUnseen cvs repository 06/07/2002 welch@panasas.com lib/mime.tcl - Move the modification of application/octet-stream MIME types up a bit to be before the decision is made to display the type (patch from Diego Zamboni) cvs repository 06/06/2002 welch@panasas.com lib/ftoc.tcl - Fix to Ftoc_ClearMsgCache for unset vs. array unset buglet. cvs repository 05/01/2002 Hal DeVore lib/sedit.tcl - moved calls to SeditSend hooks to much earlier cvs repository 04/30/2002 welch@panasas.com A whole collection of patches. If marked with ** then I've lost track of who gave them to me and I apologize for that: exmh-strip.MASTER: added pref initialization to quiet errors caused by changes elsewhere in the main body of exmh install.tcl: fixed errors that occur when you try to display a dialog box (e.g., the Verify window) that is already displayed lib/addr.tcl: a new set of options for configuring LDAP (Mark Bergman) lib/extrasInit.tcl: help text updates about the uquoteAdd resource (**) lib/faces.tcl: fix for space-in-pathname problem (**) lib/fcache.tcl: New Feature! display the count of unseen messages in the folder cache. (Paul Menage) lib/html_get_http.tcl: trap errors from bad http: links lib/inc.tcl: tweaked feedback about inc'ed messages to do case-insensitive grep for Subject: (**) lib/mime.tcl: for for space-in-pathname problem lib/pgpExec.tcl: eliminated Exmh_Debug message that could dump out a massive keyring to the log, taking many many seconds (**) lib/unseenwin.tcl: fix to tolerate space-in-folder-name (I think) (**) cvs repository 04/04/2002-04/17/2002 cwg-exmh@deepeddy.com various files - some more code cleanup and a whole bunch of sequence related code tuning. cvs repository 04/03/2002 cwg-exmh@deepeddy.com lib/app-defaults, lib/app-defaults-color, lib/buttons.tcl, lib/exwin.tcl, lib/ftoc.tcl, lib/msg.tcl, lib/pick.tcl - Added 'Sequences...' menu; some code cleanup and a few bug fixes from the last change. cvs repository 03/28/2002 cwg-exmh@deepeddy.com lib/app-defaults-color, lib/app-defaults-mono, lib/exwin.tcl, lib/fdispColor.tcl, lib/ftoc.tcl, lib/ftocColor.tcl, lib/help.tcl, lib/mh.tcl, lib/msg.tcl, lib/pgpMain.tcl, lib/scan.tcl, lib/thread.tcl - Generalized unseen handling to display other sequences besides unseen. cvs repository 01/25/2002 slipcon@mercea.net lib/html/ppp.howto.html - fixed postfix instructions, via Kevin Oberman again. cvs repository 01/26/2002 valdis.kletnieks@vt.edu lib/ftp_get.tcl - add a 'catch' in case an FTP dies early, so we don't throw an error unsetting data(fd) if it was never set.. cvs repository 01/26/2002 valdis.kletnieks@vt.edu lib/app-defaults-color, lib/main.tcl, lib/html/custom.html - drop the need for c_st_background color setting, use same scheme as lib/sedit.tcl to propogate the value. The 'background msgs' color stays c_st_bg_msgs cvs repository 01/25/2002 slipcon@mercea.net lib/html/ppp.howto.html - added postfix instructions, using Kevin Oberman (oberman@es.net)'s diff cvs repository 01/24/2002 valdis.kletnieks@vt.edu lib/sedit.tcl - missed a readonly/disabled issue for Tk8.4 (status field) cvs repository 01/24/2002 valdis.kletnieks@vt.edu exmh-bg.MASTER, lib/main.tcl, lib/app-defaults-color, lib/html/custom.html So there *was* code using c_st_background. That color specification is now c_st_bg_msgs, and exmh-bg no longer tries to lookup a colorspec but just passes 'background' to Exmh_Status. cvs repository 01/23/2002 valdis.kletnieks@vt.edu lib/app-defaults-color, lib/html/custom.html - Default for c_st_error is now red, and the default for c_st_warn is purple (be more consistent with usual meaning of a red message indicating an error) cvs repository 01/23/2002 valdis.kletnieks@vt.edu install.tcl, lib/main.tcl - Do version test as per Jeff Hobb's suggestion. cvs repository 01/22/2002 valdis.kletnieks@vt.edu lib/aliases.tcl, lib/background.tcl, lib/env.tcl, lib/error.tcl, lib/faces.tcl, lib/flist.tcl, lib/folder.tcl, lib/folderNew.tcl, lib/inc.tcl, lib/main.tcl, lib/mime.tcl, lib/msg.tcl, lib/pick.tcl, lib/print.tcl, lib/scan.tcl, lib/seditSel.tcl, lib/source.tcl, lib/thread.tcl, lib/urlFace.tcl Clean up red/purple/blue hardcoded values for Exmh_Status lib/app-defaults-color, lib/main.tcl - clean up dead unused code for c_st_background (which is used as a *foreground* color gaak) c_st_background is now the *background* color for the status field cvs repository 01/22/2002 valdis.kletnieks@vt.edu install.tcl - tkEntryBackspace handling for Tk8.4a2 and later namespaces cvs repository 01/22/2002 valdis.kletnieks@vt.edu lib/main.tcl - add new procedure Tcl_Tk_Vers_Init to do per-release tweaking of the environment. Currently used to re-expose commands moved to private namespace in Tk8.4a2. cvs repository 01/20/2002 valdis.kletnieks@vt.edu lib/ispell.tcl - fix old syntax error finally caught by tcl8.4a4. cvs repository 12/07/2001 kchrist lib/pgpExec.tcl - Fixed "GPG silently ignores untrusted keys during encryption" bug. Thanks to Ben Escoto. cvs repository 12/06/2001 kchrist lib/mime.tcl: Do not call viewer if mailcap rule has needsterminal attribute. When using Mime_Magic to replace application/octet-stream make sure to replace entire content-type and not just the "octet-stream" subtype. lib/seditExtras.tcl: Fixed a bug in SeditInsertFile that caused text to be lost when quoting. Previous code assumed headers were always present and had to be removed. lib/pgpMain.tcl: Fixed the "Always choose the sign key." option. Fixed a clearsigning bug. Modified interpretation of app/pgp header to avoid hang. lib/pgpExec.tcl : Exmh can now parse the GnuPG options file and lib/pgpGpg.tcl : identify the "default-key" (same as "myname" in PGP). Added "--status-fd 2" to args_decrypt so that the output can be parsed with Pgp_InterpretOutput. cvs repository 11/21/2001 Brent Welch lib/main.tcl: Moved WM_SAVE_YOURSELF registration a bit later because it has an Exmh_Checkpoint side-effect that causes exmh to forget the current folder. exmh.strip.MASTER fixed #! line so it gets installed right. lib/mh.tcl: Plugged file descriptor leak in Mh_ParseProfile Fixed ParseProfile to handled indented continuation lines lib/seditExtras.tcl: Tweaked paragraph formatting in Sedit to honor requested line length and the anticipated repl prefix length. custom.html: fixed m_tagnames documentation software.html: fixed uudeview URL cvs repository 11/15/2001 Valdis Kletnieks lib/folders.tcl: Fix typo in function name cvs repository 08/23/2001 kchrist lib/pgpWWW.tcl: Comment in switch statement causing problems. cvs repository 07/13/2001 Brent Welch lib/exmh.install.tcl: Changed release date to 7/13 lib/html/index.html: Changed release date to 7/13 tagged and released exmh 2.5. CVS tag exmh-2-5 cvs repository 07/13/2001 Brent Welch lib/mime.tcl: Fixed Mime_WithTextHiding to catch errors and returns from its uplevel call, fixing a file descriptor leak from Mime_ShowMsWord cvs repository 07/11/2001 Brent Welch ftp.expect.MASTER: inc.expect.MASTER: Changed to a #!/bin/sh header with exec hack to be able to insert the -- flag to expect install.tcl: Changed the expect patching to match the above change lib/pgpMain.tcl: lib/mime.tcl: Changed MsgTextHighlight to Msg_TextHighlight lib/msgShow.tcl: Added Msg_HighlightInit lib/sedit.tcl: Added SeditBeautify from John Beck lib/seditBind.tcl: Added "highlight" virtual function to sedit bindings lib/app-defaults: Added binding to sedit to beautify it. cvs repository 07/10/2001 Brent Welch lib/editor.tcl: A -- is passed to the exmh-async script to turn off any argument/flag parsing by wish. This means you can safely pass "-c" or "-geometry" arguments to the programs spawned by the exmh-async wrapper script. exmh-async.MASTER: Removed a split/join construct that screwed up attempts to pass arguments like {cal SetSyn("mail")} to editors. lib/mime.tcl: Fix to highlighting text range from John Beck. lib/msgShow.tcl: Tweaks to highlighting from John Beck. cvs repository 07/09/2001 Brent Welch Makefile: exmh.README: exmh.CHANGES: lib/html/exmh.README.html: lib/html/index.html: lib/html/software.html: version.sed: exmh.install: Changing version number to 2.5 exmh-bg.MASTER: exmh.MASTER: Fixed initialization of exmh(userLibrary) inc.expect.MASTER: Fixed !# line so it gets installed right lib/app-defaults-color: Added resources for message highlighting based on the jcl-beautify code. lib/autorefile.tcl: Contributed code by John Carroll lib/fdispColor.tcl: lib/fdisp.tcl: Added use of c_unseenBg and c_movedFg color resources for further refinement of unseen and moved messages. lib/inc.tcl: Cleanup of Inc_Expect lib/mailcap.tcl: Fixed bug in mailcap parsing code that didn't quote & in rules, leading to message corruption in SaveAttachments code. lib/mh.tcl: minor tweak to variable unset lib/mime.tcl: Added highlightText option and calls to MsgTextHighlight. * lib/msgShow.tcl: Added MsgTextHighlight and the jcl-beautify code, with minor changes to separate the bug reporting header highlighting into a different hook. There is now a "message show" hook that operates on the whole message, a "message highlight" hook that only operates on the text regions of a message. lib/pgpMain.tcl: Added call to MsgTextHighlight. lib/pop.tcl: Fixed Pop_Dialog so it works right with multiple hosts. cvs repository 05/31/2001 kchrist lib/scan.tcl: Allow arguments in scan-proc configuration. lib/app-defaults: Have "Use message as draft" call Msg_CompUse. This sidesteps an internal bug in MsgComp. To fix the bug MsgComp needs to be drafts-folder aware like Mh_CompSetup. cvs repository 05/18/2001 bmah lib/extrasInit.tcl: lib/pgpBase.tcl: PGP detection code now tries to execute a program (e.g. "gpg --version") and parse the output to determine presence of installed versions. Former versions only checked the existence of files. cvs repository 05/16/2001 kchrist lib/sedit.tcl: Make sure exmh($id,action) survives a 'Keep on send'. cvs repository 05/15/2001 Brent Welch Makefile: exmh.README: exmh.CHANGES: lib/html/exmh.README.html: lib/html/index.html: lib/html/software.html: exmh.install: Changing version number to 2.4 version.csh: version.sed: Scripts to help with version changes. (I don't think I ever committed things at this point - hence 2.5) cvs repository 05/14/2001 kchrist Fixed a bug in which a corrupt context would prevent exmh from starting. Problem was caused by direct calls to 'repl' instead of wrapping them inside a (context-aware) MhExec call. lib/main.tcl: Moved nmh-vs-mh identification to Mh_Init procedure lib/mh.tcl and replaced 'exec repl...' calls with 'MhExec repl...' calls. Note that MhParseProfile is called first since MhExec may need $phProfile(path). cvs repository 05/11/2001 kchrist A bunch of changes having to do with making sure exmh($id,action) is there when we need it. Also... Replaced Sedit_Mailto with Msg_Mailto (extending Ovidiu's patch). Replaced exmh(ctype) with exmh($id,action). lib/editor.tcl: Set exmh($id,action) in Sedit_DraftID. lib/error.tcl: Call Edit_DraftID instead of EditWhatNow directly so that exmh($id,action) gets set. lib/html_links.tcl: Call Msg_Mailto instead of Sedit_Mailto. lib/mh.tcl: Made sure exmh($id,action) is set when comp'osing and reset when done. lib/msg.tcl: Turned Msg_CompTo into Msg_Mailto as replacement for Sedit_Mailto. Made new Msg_CompTo. Removed exmh(ctype). Set exmh($id,action) in MsgComp and Msg_Edit. Moved DecodeURL from seditExtras into here and renamed it to MsgDecodeURL. lib/sedit.tcl: Don't check if exmh($id,action) or pgp(version,$id) exist before using them. If they don't it is a bug we should catch and fix. Modified call to SeditSetIsigHeaders. lib/seditExtras.tcl: Modified parameters to SeditSetIsigHeader. Replaced Sedit_Mailto with a stub that calls Msg_Mailto. Removed DecodeURL. lib/tclIndex: New one needed because functions were moved. lib/uri.tcl: Call Msg_Mailto instead of Sedit_Mailto in URI_StartViewer. cvs repository 05/10/2001 Brent Welch exmh.MASTER: exmh-bg.MASTER: Removed auto_reset from auto_path_update and add exmh(userLibrary) to auto_path very early. inc.expect.MASTER: Code cleanup and fix to ensure that the password is not echoed in the scan listing. lib/addr.tcl: Adopted patch for LDAP searching lib/background.tcl: Removed extra call to User_Layout from Background_Init lib/env.tcl: We only chmod exmh(tmpdir) if it does not already exist to avoid setting permissions on /tmp, /usr/tmp, etc. lib/extrasInit.tcl: Added utf-8 to possible set of text charsets This is used when setting the initial type in sedit. lib/main.tcl: Removed the exmh(userLibrary) preference setting. This is hardwired (the code is in exmh.MASTER) to be either ~/.exmh/lib (a new, preferred value) or ~/.tk/exmh (the old, historical location) The first directory that exists is used. lib/pop.tcl: Minor tweak to focus settings in password dialog. lib/seditBind.tcl: Added auto_loads to try and avoid loosing bindings when Tk library files are loaded. cvs repository 04/20/2001 Ovidiu Predescu lib/uri.tcl (URI_StartViewer): Invoke Msg_CompTo instead of Sedit_Mailto to correctly support external editors. lib/sedit.tcl (Sedit_Start): Better check for PGP variables so we don't get a runtime error if PGP is not fully enabled in a particular installation. lib/msg.tcl (Msg_CompTo): Accept a generic mailto: URI as argument, instead of a simple email address. Modify the draft according to this mailto: URI so that it has the right content before being passed to the editor, which may be an external editor. cvs repository 04/10/2001 Brent Welch exmh-strip.MASTER: extracted code from mime.tcl into a utility script that strips attachments from mail and replaces them with message/external-body parts that reference the extracted file. lib/app-defaults: Added mappings from utf-8 charset to iso10646 fonts lib/env.tcl: switched from TMPDIR environment variable to exmh(tmpdir) so that we don't pollute the environment with our choice of temp directory. This confuses some programs, especially gnuclient. lib/mime.tcl: Fixed message/external-body for the local-file access case. lib/inc.tcl: Added guard against undefined exmh(slocal) to Inc_Init. Cleaned up check against stray files (e.g., "++") in the MyIncTmp directory. lib/folder.tcl: Added Folder_Cache calls when setting the move/copy folder so that the folder appears in the folder cache. cvs repository 03/03/2001 Brent Welch lib/inc.tcl: Eliminated the use of the expect wrapper around inc for the "presort-multidrop" and "multidrop" cases. This interferes with folks that have set up their .netrc file to have passwords. lib/fdispPopup.tcl: Eliminated noisey Exmh_Debug command lib/html/exmh-faq.html: Added #24 about scan .mh_profile entries that can cause problems. cvs repository 01/19/2001 Brent Welch lib/main.tcl: fixed test for MH version. Released exmh-2.3.1 1/19/2001 Brent Welch cvs repository 01/19/2001 Brent Welch lib/env.tcl: fixed installation error that was due to the addition of Env_Init to the installer. Only showed up when you installed without the .exmhinstall cache. Released exmh-2.3 1/17/2001 Brent Welch cvs repository 01/17/2001 Brent Welch lib/flist.tcl: Added catch for file system errors that could cause Flist to stop working - both when hitting the button and from the background process. cvs repository 01/15/2001 Brent Welch These files embed version information: Makefile exmh.README exmh.install lib/html/index.html lib/html/software.html lib/html/exmh.README.html lib/extrasInit.tcl: Moved POP3 mail host into the top-ten preferences. lib/html/exmh-faq.html: Added FAQ about using a POP3 mail server. lib/bitmaps: added a contributed set of bitmaps to replace text buttons. You'll need to set up your exmh-defaults to get these. See the lib/bitmaps/exmh-defaults file for an example. install.tcl: added call to Env_Init lib/env.tcl: Fixed it so that it doesn't chmod /tmp if that's what TMPDIR is set to. cvs repository 01/12/2001 Brent Welch lib/env.tcl - fix for symlink attack. Exmh now chooses /tmp/ as the default tmp directory. You can also set TMPDIR or EXMHTMPDIR, which was true in previous versions of exmh already. lib/pop.tcl - improved the password prompting dialog. inc.expect - fixed this to deal with the case where inc does *not* prompt you for a password. cvs repository 01/03/2001 Bruce A. Mah lib/pgpPgp5.tcl - Add +force to correct a problem with verifying the signatures of PGP5 clearsigned messages. From Dave Tweten , via the FreeBSD Project. cvs repository 01/03/2001 Hal DeVore exmh.TODO removed item 24 - support for nmh 1.0, already done removed item 33 - change name of /tmp/scancmds, it's already dependent on [Env_Tmp] cvs repository 01/03/2001 Hal DeVore lib/error.tcl - Remove file [Env_Tmp]/exmhErrorMsg if it exists prior to writing to it. Addresses a bug reported to BUGTRAQ. cvs repository 12/13/2000 Brent Welch lib/html/sedit.html - Added explanation from John Klassa about the Filter mechanism in Sedit. lib/folder.tcl - applied a fix for auto-packing folders from Chris Keane (I think it was Chris) The bug lead to incorrect scan listings when you used auto-pack. cvs respository 12/11/2000 Hal DeVore lib/sedit.tcl - removed duplicate SeditSetHeader proc cvs respository 11/22/2000 Hal DeVore lib/html/guide.html - Corrected a couple of improperly closed tags lib/sedit.tcl - patch from Chris Keane to eliminate the removal of charset in SeditSetHeader proc cvs repository 11/17/2000 Brent Welch lib/glimpse.tcl - Grouped some expressions with { } to avoid double-substitutions on file and directory names. If they had $ in them it would raise errors. cvs repository 11/08/2000 Brent Welch lib/inc.tcl - Added the option to use an expect script that wraps the "inc" program and deals with the password prompt. inc.expect.MASTER - the expect script cvs repository 10/25/2000 Anders Eriksson lib/mime.tcl - Headers are now displayed in the order expressed in mhProfile(header-display) cvs repository 10/23/2000 Brent Welch lib/ispell.tcl - replaced some debug "puts" with Exmh_Debug lib/uri.tcl - trim white space off the URI that is matched to handle the funky Visit links. lib/glimpse.tcl - fixed glimpse -V test during startup to handle both old and new versions of glimpse. cvs repository 09/21/2000 Valdis Kletnieks lib/glimpse.tcl - Glimpse 4.12.6 output /Mail//folder - the double slash gave a regexp indigestion. Fix to accept / or // after Mail cvs repository 09/21/2000 Valdis Kletnieks lib/pgpExec.tcl - fix 'set result' so 'PGP Get Key' and 'PGP Generate Key' work. cvs repository 09/21/2000 Valdis Kletnieks lib/pgpPgp65.tcl - fix a stupid regexp problem so it finds RSA keys cvs respository 09/15/2000 Hal DeVore lib/inc.tcl Added code to allow the use of procmail or any other mail-fetching-and-filtering tool directly from exmh. Original patch developed by Carl D. Roth, code updated and merged into current exmh by Chris Keane. cvs respository 09/13/2000 Hal DeVore lib/html.tcl Fixed preferences item spelling mismatch problem and solution pointed out by Ben Escoto cvs respository 09/07/2000 Hal DeVore lib/addr.tcl Fixed problem with some address book preferences getting clobbered. cvs respository 08/30/2000 Hal DeVore lib/seditMime.tcl applied patch from Chris Garrigues to prevent flowing of mhn directives when running sedit with formatting on send. cvs repository 08/28/2000 Valdis Kletnieks lib/html/software.html: Document 8.3.2 as most recent Tk/Tcl. cvs repository 06/28/2000 Hal DeVore lib/mh.tcl: added -noheader to "exec scan" in Mh_Forw_MungeSubj to prevent breakage when user .mh_profile specifies "scan: header", problem found by David Chin cvs repository 06/28/2000 Hal DeVore lib/folder.tcl: Got rid of a hardcoded path to ~/Mail cvs repository 06/27/2000 Bruce A. Mah lib/seditExtras.tcl: Add an "undo" feature for sedit shell, from John Klassa . cvs repository 06/27/2000 Hal DeVore lib/{mh.tcl,msg.tcl}: Add upward search for components, forwcomps, and replcomps. Add search for distcomps also. cvs repository 06/26/2000 Bruce A. Mah lib/{extrasInit,sedit,seditExtras}.tcl: Add the ability for sedit to filter the selected text region through an arbitrary UNIX command, from John Klassa . Released exmh-2.2 6/23/2000 Brent Welch cvs repository 06/22/2000 Valdis Kletnieks lib/receipt.tcl - generate proper Final-Recipient: field cvs repository 06/22/2000 Bruce A. Mah lib/html/exmh-faq.html: Added FAQ #15a on folder-specific template files. lib/html/exmh-faq.html: Added FAQ #23 on keeping sender's address from appearing in the cc line, written by Pete Gelbman . cvs repository 06/21/2000 Bruce A. Mah lib/html/custom.html: Updated "Preferences Sections" and "Code Organization". cvs repository 06/21/2000 Valdis Kletnieks lib/main.tcl - fix MH version for UCI MH users - was using bogus variable cvs repository 06/20/2000 Bruce A. Mah lib/fdisp.tcl, lib/find.tcl: Add a preferences item to allow finds (control-s in default bindings) to start either in the FTOC or the current message. Patches from John Klassa . cvs repository 06/20/2000 Brent Welch lib/exec.tcl: Put catch around the unsets of ExecCache. Errors can occur in Pgp_Exec_Init if the path to PGP is wrong. cvs repository 06/16/2000 Bruce A. Mah lib/html/exmh-faq.html: Add FAQ #22 about giving preference to displaying text/plain over text/html. Fix minor HTML glitch in FAQ #21. exmh.CHANGES: In a fit of anal-retentiveness, fix a typo. cvs repository 06/16/2000 Brent Welch (By way of Jacob Morzinski) lib/extrasInit.tcl, lib/faces.tcl, lib/flag.tcl Generalized the "slow display icon" preference item to give control over using color icons for the Exmh desktop icon as well as for the faces icons. cvs repository 06/16/2000 Valdis Kletnieks lib/app-defaults - missed a PGP menu lib/pgpBase.tcl, lib/pgpExec.tcl, lib/pgpMain.tcl - handle missing "pattern" which caused PGP 6.5 to not list private keyring. lib/pgpMain.tcl - after changing PGP version in sedit, wrong PGP version used in 'select key' dialog. cvs repository 06/15/2000 Valdis Kletnieks lib/main.tcl, lib/sedit.tcl, lib/seditMime.tcl - output MH version as well as Exmh on X-Mailer: line lib/pgpExec.tcl, lib/pgpGpg.tcl, lib/pgpPgp65.tcl - make PGP Comment: line track the Exmh version actually used... cvs repository 06/12/2000 Brent Welch sedit.tcl: Fixed auto-sign bug having to do with {$t} in app-defaults. Makefile, exmh.install, exmh.README, html/index.html, html/software.html Rationalizing version number to 2.2 Released exmh-2.1.2 6/8/2000 Brent Welch cvs repository 06/08/2000 Valdis Kletnieks Support for PGP 6.5. Added new file lib/pgpPgp65.tcl. Added PGP 6.5 config to lib/pgpBase.tcl, lib/extrasInit.tcl, exmh.install, lib/app-defaults, and lib/html/PGP.html. Fixed a check in extrasInit - it assumed a PGP version was present if the $pubring and $path for the version were there. I added a check that the 'pgp verify' command was present. Otherwise it thinks that 5.0 is available if 6.5 is present. lib/pgpWWW.tcl - provide a working default URL. cvs repository 06/08/2000 Hal DeVore lib/extrasInit.tcl: Corrected help text for Play Multiple cvs repository 06/08/2000 Hal DeVore lib/extrasInit.tcl: Clarified wording of help for Play Multiple Also added help about globbing for sound file paths lib/mime.tcl: nearly lost this change from Christopher Hall: proc MimeParseSingle reads the first line of the body _before_ Mime_SetFileEncoding is called; therefore the first line is in the default encoding for the file (guess this is us-ascii). The first line of the display will be in the wrong encoding. cvs repository 06/07/2000 Scott Lipcon misc/RPM/: added and fixed 2.1.2 RPM generation lib/sound.tcl: added ~ glob to sound file paths (untested) Forgot to update exmh.CHANGES, sorry :) cvs repository 05/30/2000 Bruce A. Mah lib/seditMime.tcl: Fix a bug introduced in last commit to this file; when creating a multipart message, don't assume where the separator is, just scan for it. cvs repository 05/09/2000 Valdis Kletnieks exmh.TODO: remove following 2 patches from #25, add RFC2646 as #50 Also, removed line item 8, it was already in the CVS tree.. lib/inc.tcl: add preference item for 'flist-at-startup' lib/exwin.tcl, lib/widgetText.tcl: add preference item for automatically scrolling to next message cvs repository 05/08/2000 Valdis Kletnieks lib/html/software.html Document Tk/Tcl 8.3.1 lib/uri.tcl Merge in minor fix from Hal Devore, lost somewhere around 2.0epsilon lib/main.tcl Timestamp the logfile cvs repository 05/08/2000 Brent Welch lib/app-defaults, lib/sedit.tcl: Restored the use of { } in the Sedit app-defaults values so we can tolerate spaces in the drafts folder name. Changed the uses of "eval list" to "subst" in sedit.tcl so the bracing trick works in those cases. lib/html.tcl, html_images.tcl: Added an option to disable image loading in HTML lib/html/guide.html: fixed minor typos. cvs repository 04/19/2000 Brent Welch lib/ftoc.tcl, lib/folder.tcl: Added Ftoc_LastFolder and Folder_Previous so you can go back to the folder you were just in. lib/flist.tcl: Added "force" argument to Flist_FindAllFolders lib/folder.tcl: Added Folder_CheckPointShared, Folder_IsShared, Folder_FindShared to support the notion of folders shared by other exmh users. lib/mh.tcl: Changed to use mhProfile(sendproc) instead of "send" lib/msg.tcl: Added call to Folder_CheckPointShared lib/seditMime.tcl: Tweaks to handle proper positioning of the insert cursor. One for --- header separators, another for when you delete the last character in a part. lib/seditQP.tcl: Took out extra Mime-Version header cvs repository 04/19/2000 lib/html/software.html nmh 1.0.4 is out - vkletnieks cvs repository 04/18/2000 lib/seditExtras.tcl Add better support for composing RFC2017 URL external-references Still need to add better support for displaying them - vkletnieks cvs repository 04/18/2000 lib/app-defaults, lib/scan.tcl, lib/seditBind.tcl Handle embedded blanks better - vkletnieks, patch by Jacob Morzinski cvs repository 04/18/2000 lib/PgpDecryptExpect, lib/PgpExec.tcl, lib/pgpGpg.tcl, lib/pgpPgp5.tcl Use ASCII quote character - vkletnieks, patch by Jacob Morzinski cvs repository 04/05/2000 lib/html_head.tcl, lib/html_links.tcl - Use app-defaults c_link, c_alink values for links. - vkletnieks cvs repository 03/29/2000 Updated lib/html/software.html - note *actual* latest versions, removed some dead mirrors, and added a note that nmh 1.0.3 is recommended due to security issues. -vkletnieks cvs repository 03/23/2000 Some work on the FAQ a) Added new question 2c, dealing with RFC2047 encoded headers, with a cross-reference under question 18 (FTOC). b) Did some minor markup changes to question list c) Did some markup revisions to 14 (mailing lists). Also added pointer to mailing list archive and info on digested exmh-user list. d) Markup revisions and additional info in question 15 (templates). It noted 4 types of templates but only listed 3. Now it has info on 4 MH plus 1 new nmh template. -haldevore cvs repository 02/29/2000 Applied patch to speed up pick -Dick Wesseling via haldevore Applied patch to allow parentheses in address book entries -Mats Bengtsson via haldevore Applied patch to limit encodings to one for which we have fonts -Marc Boucher via haldevore Happy leap century day! cvs repository 02/02/2000 Fixed hard-coded '-wrap word' -vkletnieks cvs repository 02/02/2000 Fixed hard-coded 'config -cursor xterm' -vkletnieks cvs repository 02/01/2000 Fixed regexp for glimps version detection -vkletnieks cvs repository 12/6/1999 Added character encoding support to LDAP lookup -iko cvs repository 12/2/1999 Applied Burkhardt patch for specifying POP host with -host flag Fixed "double page up" bug in HTML by eliminating redundant bindings Tweaked error message in install.tcl cvs repository 11/08/1999 Roll back 11/04/1999 bug fix and re-implement it in a different way. -kchrist cvs repository 11/05/1999 Removed app-defaults assumption of PGP use when treating multipart/signed or multipart/encrypted -kchrist cvs repository 11/04/1999 Disable PGP sign and/or encrypt when doing a redistribute. -kchrist cvs repository 10/29/1999 Fix bug introduced with previous PGP options change. -kchrist cvs repository 10/28/1999 PGP options were not being preserved on a re-edit. Fixed a crash when not-enabled PGP versions were selected in sedit. -kchrist cvs repository 10/27/1999 Quick application/pgp support fix. -kchrist cvs repository 10/25/1999 Added a dropKeys pattern to pgpGPG.tcl. Simplified PGP GUI by removing "detached" signature option. Problem was that MIME+standard includes a copy of the message being signed in the signature attachement. What really should be used is MIME+detached. Decided to overload the meaning of "standard". If the format is plain, standard means "binary". If the format is anything else, standard means "detached". Less flexibility but better chance of "doing the right thing". -kchrist exmh-2.1.1 Released, 10/15/1999 cvs repository 10/12/1999 Fixed a bug that caused a new sedit window to bomb if the PGP selection for new windows was not supported. -kchrist cvs repository 10/07/1999 Changed documentation string for quote file name to indicate it is created relative to the exmh startup directory. Fixed a bug in sign+encrypt processing when composing a MIME message. Added a couple of bugs to the list to remind me of what still needs to be done. -kchrist cvs repository 09/29/1999 Fixed a bug in the shorten output processing of GPG. -kchrist cvs repository 09/27/1999 More PGP changes. Consolidated passphrase entry to sedit field or pgpExec routine. Made the pgp-sedit field aware of pgp(keeppass) and pgp(echopass). Moved pgp(keeppass), pgp(echopass) and pgp(grabfocus) to PGP General Interface. Fixed a minor bug left over from my previous GUI changes. -kchrist cvs repository 09/22/1999 Changed the PGP interface, basically the stuff under the Crypt... button. The hope is that the change will help make the different sign options a bit clearer - kchrist exmh-2.1.0 Released, 9/17/1999 cvs repository 09/17/1999 Fixed RPM build, and added spanish support to the RPM, thanks to Francisco Monserrat -slipcon cvs repository 09/15/1999 Typos in getnews.tcl - cwg cvs repository 09/03/1999 Allow (again) spaces in address search strings. (addr.tcl) - kchrist cvs repository 09/01/1999 Fixed text/plain to application/pgp hack in mime.tcl so it ignores the format parameter of text/plain. -kchrist cvs repository 08/25/1999 Fixed some problems with not timing out PGP subkeys (e.g. DSS keys for PGP5/GPG). --bmah. Eliminate last vestige of PGP passphrases showing up in debugging logs. --George Ross via bmah. cvs repository 08/24/1999 Importing keys from email keyserver queries now works. Attaching keys to an email message is now RFC 2015 compliant (content-type: application/pgp-keys instead of application/pgp). --Kevin.Christian@lsil.com via bmah. Made reply-to-all invoke repl -group if repl claims to support a -group flag (i.e. is nmh). Adapted from Debian 2.0.2-7 package. (iko) cvs repository 08/22/1999 Fix a few bugs related to email PGP querying (queries now can go out). Use Exmh_Status to let user know what's happening during an email query. --Kevin.Christian@lsil.com and bmah. Sanitize PGP info out of debugging logs. --George Ross via bmah. Delete More...->old PGP->Encrypt cascaded menu, due to apparent lack of need for this functionality and difficulty in getting it correctly implemented. --bmah. cvs repository 08/19/1999 Change address book expansion to NOT insert new header lines as this broke the "continue lookup" feature. Also changes to allow address expansion on ANY header line (doc changes still to be done). -Kevin.Christian via haldevore cvs repository 08/17/1999 PGP without seditpgp works again. -bmah Wheel mouse support added, enable it in the Windows + Scrolling dialog. - slipcon cvs repository 08/13/1999 Don't try to coerce text/plain PGP messages to application/pgp unless PGP is actually enabled. --bmah Really fix problems with 8-byte GPG keyIDs and keyservers this time. --Kevin.Christian@lsil.com, via bmah Rudimentary support for LDAP --Jason Day and cwg If we ask the user for help in picking the PGP key to use for a receipient and they cancel the resulting dialog, generate an error (instead of asking the user ad infinitum). --bmah cvs repository 08/12/1999 Fix a number of key/passphrase management problems: pgpsedit now manages PGP versions, keys, and passphrases on a per-window basis. Decryption now works when no passphrases are cached. One timeout parameter controls passphrases for all PGP versions. seditpgp UI slightly modified. --bmah Get rid of "PGP Preview" menu item in sedit left over from debugging. --bmah cvs repository 08/10/1999 Properly use [Env_Tmp] in the below patch -cwg Ignore high-order bytes of key IDs returned by GPG for compatability with keyservers. --bmah Properly process PGP/MIME messages that have boundary characters containing regular expression special characters. --bmah cvs repository 08/05/1999 Prompt before executing buttons on html pages which are either non-local or in /tmp. -cwg cvs repository 08/04/1999 Fixed problems with not providing a password under pgp2 -cwg Renamed the *.n.html pages and rephrased links to them -cwg Got passphrase timeout to work yet again -cwg cvs repository 08/03/1999 Display the body of a message which fails to be decoded by PGP. -cwg Finished to reveal more buttons that do the installation.

The installer has many fields in a scrolling list. Each field value is used to patch exmh.MASTER in order to make the exmh script. Most of the settings are file or directory names. Make sure the file system pathnames are correct for your system. The fields are described below.

The wish pathname is for the program that runs exmh. Tk 8.0 or higher (e.g., Tk 8.4) is required.

By default, the program is installed as "exmh", and it also uses related scripts named "exmh-bg" and "exmh-async". If you want to install it under an alternate name, use the "Name of main exmh script" setting to change the base name.

You may not have some support programs or packages. In this case, just delete the default value and leave the field blank.

Recommended Packages

See exmh.README.html for pointers to these.

  • The metamail program that handles unknown (by exmh) MIME formats. This also includes mimecode that handles base64 and quoted-printable encodings used to transmit 8-bit data safely in mail messaegs. This is highly recommended. If you use 8-bit character sets, then you must have this package to properly encode messages.

Optional Packages

See exmh.README.html for pointers to these.

  • The expect program. This can be used to do FTP transfers of MIME message/external-body messages of subtype anon-ftp.
  • The facesaver database. Exmh needs to know the root directory of the database and then the set of subdirectories under that which contain directory trees of face bitmaps.
  • Glimpse is a search tool that can help you find mail messages by their content.
  • The play program that plays audio files.

Reminder

Check out the optional slocal.patch and folder.patch files. These are optional - see the man page for details.

Field descriptions

  • Wish absolute pathname. Exmh is a script. It needs to be run by the Tcl/Tk shell, "wish". Enter the complete, absolute pathname.
  • Exmh version number. Do not change this so that automatic bug reports properly reflect the version of exmh in use.
  • Name of main script. This lets you change the name from exmh to something else, like "exmh2" or "exmh-solaris".
  • Error mailing target. Change it if you want to see errors at your site. Otherwise I'll get them, which is OK.
  • MH binary directory. The directory that has MH programs like inc, send scan, folders, etc.
  • MH slocal program. Use for presorting mail. This is in the MH library directory. Give the complete pathname.
  • Metamail bin directory. The home for metamail and mimencode. These programs are required by exmh for MIME handling.
  • System mailcap file. This file has rules for metamail that describe how to view MIME parts. Exmh uses these rules, too.
  • System mime.types file. Maps file extensions into MIME types. Used by Exmh to set the mime type correctly for attachments when composing a MIME message. Also used by web servers to work out the MIME type of files they're delivering and web browsers to work out what to do with file:... type URIs so your sysadmin may have installed one (maybe in /usr/etc or /usr/local/etc). Default is to use the one which will be installed in the Script Library directory.

(The following are for optional packages. Leave them blank if you do not have the related package. There are more required fields described after these)

  • Expect program. Only needed if you use the "expect" method for FTP transfers. This is the most reliable method.
  • Root for faces. The facesaver directory. It has subdirectories that correspond to different faces (i.e., picons) databases.
  • Search path for user faces. This is a list of directory names relative to the root of the faces databases.
  • Search path for generic faces. This is a list of directory names relative to the root of the faces databases.
  • Default domain. This is used in faces lookup to fully qualify addresses.
  • Faces file suffixes. These are the file extentions that are used in your faces database. Narrowing this speeds face lookup.
Faces example: Suppose you have a directory /usr/local/faces that contains these subdirectories: domains, misc, unknown, usenix, users, and local. /usr/local/faces is your "Root for faces". Each of the subdirs is the root of a directory hierarchy that mirrors domain names. You'll have domains/com, domains/edu, as well as users/com and users/edu, for example. The databases are split into user and generic categories to help find real faces before more generic icons.
  • PGP bin. The directory that contains the PGP binaries.
  • Glimpse bin. The directory that contains the glimpse and glimpseindex programs.
  • Audio play program. A program that plays .au files

More Required Fields

  • Script Library. The runtime location of the exmh .tcl files.
Note that the "Script Library" and the "Install lib directory" are usually the same place. The script library is the runtime value of the library directory, while the install lib directory is the install-time value. Ordinarily they should be the same. If you have AFS, you might need to set these two differently because of read-only volumes.
  • Install bin directory. The place to install the main exmh script.
  • Install man directory. The place to install the man pages.
  • Install lib directory. The place to copy the .tcl scripts.
The "Install lib Library" should be private to exmh (unshared with other apps). In addition, it cannot be the same place as ./lib. You have to let the install procedure copy the TCL library files elsewhere. The Verify does not check for this, and you'll get an error on audi.tcl as it removes itself before copying onto itself...

Install Commands

The Test button runs exmh and automatically switches the script library run-time value to "./lib" for the duration of the test.

When you press "Patch" the configuration is saved in the file named .exmhinstall. If you save this to an alternate name (e.g., .exmhinstall.sun4) you can use the button to choose among ../*/.exmhinstall* files.

After you set things up, then

  1. - apply site-dependent patches to exmh.
  2. - compute the auto-load library index.
  3. - run the patched script.
  4. - see what the Install will do.
  5. - install exmh.

More Exmh Documentation

} exmh-2.9.0/version.bash0000755000170700017070000000102113201227060014327 0ustar valdisvaldis#!/bin/bash # To change the version, first edit the Makefile and # change the version there, and frob the patterns in # version.sed. Then type "make version" # You still want to add release notes to # exmh.README and probably the other html files. for f in Makefile exmh.README lib/html/index.html lib/html/software.html ; do echo $f sed -f version.sed < $f > $f.new mv $f $f.old mv $f.new $f diff $f.old $f done echo "Edit lib/html/exmh.README.html by hand" echo "Use PatchVersion to fix exmh.install" exmh-2.9.0/exmh.TODO0000644000170700017070000002530213201227060013440 0ustar valdisvaldis ---------------------------------------------------------------------- Number: 2 Priority: Med Scope: Wide Complexity: High Status: Improve/simplify font handling. See especially the mime preview window and the message clip window (which may be the same set of widgets). ---------------------------------------------------------------------- Number: 3 Priority: Med Scope: Narrow Complexity: Low Status: Incorporate mime-forwarding (is this already there?) as is used by many "exmh hackers" already but with a look at Jerry Peek's section on "mforw". ---------------------------------------------------------------------- Number: 6a Priority: Med Scope: Complexity: Status: Improve handling of slow access to files. ---------------------------------------------------------------------- Number: 7 Priority: Med Scope: Complexity: Status: Improve ability to run multiple exmh instances to the same X server and the same mail folders and anywhere else there might be problems ---------------------------------------------------------------------- Number: 8 Priority: Med Scope: Complexity: High Status: Add ability to have multiple "current" messages being viewed ---------------------------------------------------------------------- Number: 9 Priority: Med Scope: Complexity: High Status: Add ability to have multiple FTOCs viewed. ---------------------------------------------------------------------- Number: 11 Priority: Med Scope: Narrow Complexity: Status: Convert address book to use some sort of real database instead of a dumped tcl list, or flesh out the LDAP support to provide this functionality. ---------------------------------------------------------------------- Number: 13 Priority: Med Scope: Complexity: Status: Put a real menu bar on the top of the windows and move many of the buttons into the menu bar. Those items that make sense as buttons, should remain buttons, but the look of them should be more like the ones in other applications we use. ---------------------------------------------------------------------- Number: 16 Priority: Low Scope: Complexity: Status: Composition of multipart messages is ugly. I'm sure we can do better. Also, it would be nice to be able to control where attached messages get in-lined instead of always putting them at the bottom. ---------------------------------------------------------------------- Number: 17 Priority: Low Scope: Complexity: Status: Display of multipart messages is less than ideal (ugly, but not as ugly as the composition). I (cwg) wrote it before tk had the ability to in-line graphics. ---------------------------------------------------------------------- Number: 19 Priority: Scope: Complexity: Status: Automatic detection of what style digital signatures to use. ---------------------------------------------------------------------- Number: 22 Priority: Scope: Complexity: Status: Generalized support for per-recipient twiddling of headers. Includes ability to control the "from", "reply-to" ---------------------------------------------------------------------- Number: 23 Priority: Scope: Complexity: Status: Support for group addresses (address lists) in the address book. ---------------------------------------------------------------------- Number: 25 Priority: High Scope: varies Complexity: varies Status: Incorporate patches from the New Features section of the Patch page 4.Patch to slocal.c that allows regular expressions in .maildelivery files. ---------------------------------------------------------------------- Number: 27 Priority: Med Scope: Medium Complexity: Medium Status: From: Anders Eriksson I'd like to see the possibility to run an attachment though `file` as an alternative to Content-type. Way too many attachments comes as application/octet-stream which effectively disables all mime display magic in exmh. This should be mostly working already, save some editing of app-defaults to get it to match the output of file. A quick look at the distributed app-defaults reveal that they seem to match Solaris' file. /Iko ---------------------------------------------------------------------- Number: 28 Priority: Med Scope: Narrow Complexity: Medium? Status: Always use "scan" to build or alter ftoc lines. ---------------------------------------------------------------------- Number: 29 Priority: Med Scope: Medium Complexity: Medium Status: This is now in the misc directory. Does it need to be integrated? Add John Klassa's "par" based quoter as a user option (should include user-specifiable path to par binary). ---------------------------------------------------------------------- Number: 31 Priority: Med Scope: Narrow Complexity: Low Status: Add a prompt before replacing the user's .mh_profile ---------------------------------------------------------------------- Number: 32 Priority: Low Scope: Narrow Complexity: Low Status: The html documentation says: Future versions of exmh will cache the results of decompressing the X-Face line in a personal faces database, but in the current version it just writes the file to /tmp/FACES.[pid]. Since it says this will happen, I think it belongs on the todo list. ---------------------------------------------------------------------- Number: 34 Priority: Low Scope: Narrow Complexity: Low Status: Update overview.html to current version. ---------------------------------------------------------------------- Number: 35 Priority: Low Scope: Narrow Complexity: Low Status: Review Exmh_Status and make more friendly to long messages. ---------------------------------------------------------------------- Number: 36 Priority: Low Scope: Wide Complexity: Low Status: Review handling of user-specified file and directory names, allow "~" in all cases. Change internally using glob but do NOT save the "globbed" version. ---------------------------------------------------------------------- Number: 37 Priority: Low Scope: Narrow Complexity: Status: Provide support for editing "named" lists in aliases ---------------------------------------------------------------------- Number: 39 Priority: Low Scope: Narrow Complexity: Low Status: Work over key bindings in the selection list presented when address expansion comes up with multiple hits. In particular, the return key should "do the right thing". ---------------------------------------------------------------------- Number: 40 Priority: Low Scope: Narrow Complexity: Low Status: In the "message clip" and possibly other windows you must get the focus on the scrollbar in order to scroll with the cursor keys. Brent's book discusses how to properly deal with this. ---------------------------------------------------------------------- Number: 41 Priority: Low Scope: Wide Complexity: Low Status: Ensure that all toplevel windows have handlers for WM_* messages. ---------------------------------------------------------------------- Number: 43 Priority: Low Scope: Narrow Complexity: ? Status: If x-image-url fails to load and an x-face is present it should be used. ---------------------------------------------------------------------- Number: 44 Priority: Low Scope: Narrow Complexity: Medium Status: Now less of a problem with the addition of 'Extract Message' Provide the ability to reply, forward, etc, an attached message (from a digest or forwarded or wherever). ---------------------------------------------------------------------- Number: 45 Priority: Med Scope: Wide Complexity: Medium Status: -mostly done, 6/5, slipcon - the last 3 haven't been moved yet Create a $HOME/.exmh directory to contain all the "ancillary" files used by exmh. This might include any or all of the following: .exmh-defaults X resources .exmh_addrs Address book .exmhbindings main bindings .exmhsedit sedit bindings .exmh-images x-url-image cache directory .tk/exmh user library directory .webtkcache html viewer cache $EXMHTMPDIR temp files ---------------------------------------------------------------------- Number: 47 Priority: Low Scope: Narrow (?) Complexity: High Status: In the HTML docs, under "Find SEL", I found this:
This searches the draft for the current X selection. The intent is that you select misspelled words in the output of the spell command and use this menu entry to locate them in the draft. (The find and keybinding mechanisms were stressed by this addition - expect a cleanup someday. There is no reasonable way to define keystroke accelerators for the find and still be able to change them in the Bind dialog. -don't ask...). so...that cleanup is now on the TODO. ---------------------------------------------------------------------- Number: 48 Priority: Medium Scope: Narrow (?) Complexity: Low Status: Support multiple LDAP servers in the address book ---------------------------------------------------------------------- Number: 49 Priority: Medium Scope: Narrow (?) Complexity: Low Status: Allow the addition of entries to an LDAP server if the user has write access. These might include info from: o Email addresses and names from the From: line o x-vcards o RFC2369 list headers ---------------------------------------------------------------------- Number: 50 Priority: Scope: Complexity Status: Add support for RFC2646 'format=flowed'. This will require work on both the display side and sedit/sending side. ---------------------------------------------------------------------- Number: 51 Priority: Scope: Complexity: Status: Look at GnuPG support in pgpGPG.tcl - can modulepath, siphermods, digestmods, and pubkeymods be passed as (null) rather than (deffault), so users who specify them in ~/.gnupg/options dont get a 'already loaded' error... ---------------------------------------------------------------------- Number: 52 Priority: Low Scope: Narrow Complexity: Status: Highlight sequences which are not specified in resources. (I didn't do this in my sequence highlighting code because I don't need it and I'm not sure what the right answer is - cwg) More thoughts from cwg: I think the strategy should be to move the highlighting configurations from resources into the preferences pane and then dynamically generate new configurations for sequences which turn up in folders, probably by picking a foreground color from a list of possible foreground colors. ---------------------------------------------------------------------- Number: 53 Priority: Low Scope: Narrow Complexity: Status: Pretty up the vertical orientation of the sequences window. Columns need to be coordinated between the panes to do this. May not be worth the effort. ---------------------------------------------------------------------- $Id$ # Emacs stuff # Local Variables: # mode: text # End: exmh-2.9.0/exmh.l0000644000170700017070000010531313201227060013127 0ustar valdisvaldis.\" .\" .\" $Header$ SPRITE (Berkeley) .\" .DS .\" Begin an indented unfilled display. .\" .\" .DE .\" End of indented unfilled display. .\" .\" # DS - begin display .de DS .RS .nf .sp .. .\" # DE - end display .de DE .fi .RE .sp .5 .. .TH "EXMH TOUR" 1 "December 3, 1996" "Exmh 2.0" "INTRO TO EXMH" .SH NAME exmh \- An introduction to the exmh mail user interface. .SH INTRODUCTION .PP This man page provides a quick tour through some of the basic features of .I exmh version 2.0, which provides a graphical user interface to the MH mail system. .PP After you read this tutorial you should be able to use .I exmh for your basic daily mail reading needs. You will learn how to send mail, read mail, manage your messages in folders, and adjust some of the \fIexmh\fP features by means of its Preferences user interface. .PP There is much more documentation available on-line through HTML pages that are viewable from within exmh. In particular. \fBexmh-use\fP provides information about using the more advanced features of \fIexmh\fP. If you are already an experienced email user, you may want to just read the GETTING STARTED section here and then skip to the \fBexmh-use\fP man page. \fBexmh-custom\fP describes how to customize exmh to suit your needs. \fBexmh-ref\fP lists each button and menu entry in \fIexmh\fP and explains what they do. If you are an experienced \fIexmh\fP user, this may be the most useful man page for you. .PP A cleaned up version of these man pages appear in the 3rd edition of the book by Jerry Peek, \fIMH & xmh: email for users and programmers\fP, which is published by O'Reilly & Associates. .PP Web versions of the documentation can also be found at .PP http://www.beedub.com/exmh/ .PP .SH "GETTING STARTED" .PP If you are already an MH or \fIxmh\fP user, you can start with the examples given in this tour. If you are a new user, exmh will set up your basic MH environment. This includes a Mail directory which will have one subdirectory for each mail folder, plus several files that MH mail uses for its own purposes. You also get a ~/.mh_profile file that has user settings for MH and exmh. .PP \fIExmh\fP uses the regular MH programs to manipulate your mail folders and messages. This means it is compatible with command-line use of MH programs, and its actions should be familiar if you are an experienced MH user. If you are a new MH user, then the details of running MH programs is hidden behind the graphical interface. The MH programs used by exmh are described towards the end of this man page. .PP When you run \fIexmh\fP for the first time it checks a few things in your MH profile. In particular, it depends on the Draft-Folder and Unseen-Sequence profile components. If these profile components are not present, a dialog appears and \fIexmh\fP can set them up for you. If you do not let \fIexmh\fP create them nor set them up by hand, \fIexmh\fP will not work properly. These profile entries are described in the \fBexmh-ref\fP man page. .PP \fIExmh\fP has been designed to be very flexible, although it will work just fine "out of the box". The Preference package used to adjust some of the settings in exmh is introduced in this man page, and some of the important settings are described here. A more complete guide to customizing \fIexmh\fP is given in the \fBexmh-custom\fP man page. .SH RUNNING EXMH .PP The command to start \fIexmh\fP looks like this: .DS exmh -display \fIhostname\fP:0 & .DE If your DISPLAY environment variable is set up properly, then the -display argument is not needed, and the command is even simpler. You do not need to specify a -geometry argument, although \fIexmh\fP supports one. Instead, simply position and size the window using your window manager. When \fIexmh\fP quits, it saves the geometry information so you don't have to worry about it. It does this with all its top level windows, so you can adjust their position once and then forget about it. There are more command line options described in the \fBexmh-ref\fP man page. .PP You can add the exmh command to your startup X environment by editing your startup file (like .xsession). You might also want to add it to the main menu of your window manager. The details about this vary from X system to X system, so ask your local X guru for help. \fIExmh\fP also supports the window manager session protocol, which means that session-smart window managers will automatically start exmh for you if you quit X when \fIexmh\fP is running. .SH THE EXMH DISPLAY .PP This section describes the main parts of the \fIexmh\fP display. It probably makes sense to run exmh at this point so you can follow along. There are three sets of buttons in the interface, and three main subwindows. .PP \fBMain Buttons\fP. Along the top of the window is a set of buttons and menus that apply to \fIexmh\fP itself. Quit, for example, quits \fIexmh\fP. The Help button pops up a menu, and you can select the entries there to get more on-line information about \fIexmh\fP. Use the left mouse button to select the buttons and menus. A button will change its appearance when you press it, and it will be invoked when you release the mouse over the button. If you slide the mouse off the button before releasing it, nothing happens. .PP \fBFolder Display\fP. Below the main buttons is the folder display subwindow. It has a special button for each of your top-level folders, and these are called \fIfolder labels\fP. As a new user you will see two folder labels, one for inbox and drafts. The inbox folder is for your new messages, and the drafts folder is for messages you are writing. If you have used MH (or xmh) before, then you may have many more folders that will appear in this display. The mouse bindings for folder labels are explained in the \fBexmh-use\fP man page. The \fIColor Legend\fP from the Help menu also tells you how the folder labels respond to mouse clicks. .PP \fBFolder Cache\fP. A second folder display called the \fIfolder cache\fP may appear under the main folder display. This shows the folder labels for recently used folders. If you only have a few folders this wastes screen real estate. The PREFERENCES section near the end of this man page explains how to turn this off via the Folder Cache preferences setting. If you are a first-time exmh user, Exmh tries to guess if you need this display based on the number of folders and nested folders you have. .PP \fBFolder Buttons\fP. The middle set of buttons is for operations that apply to folders. For example, you can create a new folder with the New button here. The More... button displays a popup menu with several more operations you can apply to folders. Some of these buttons will be introduced in this man page. All of these buttons and menus are explained in detail in the \fBexmh-ref\fP man page. .PP To the left of the folder buttons, summary information about the current folder is displayed. .PP \fBTable of Contents\fP. The middle subwindow of the display shows a summary of the messages in the folder. It shows the message number, the date of the message, the subject of the message, and, space permitting, the first few words of the message. Left click on a line in the table of contents to view the corresponding message. The mouse bindings for the table of contents are described in more detail in the \fBexmh-use\fP man page. .PP MH experts: The display in this window comes from both the MH scan program or MH inc programs, so it is affected by the form specification used by these programs. .PP \fBColor and Monochrome Highlights\fP. Both the folder display and table of contents windows use highlights to give you visual clues about the state of messages and folders. Your unread messages are highlighted in the table of contents and the folders that contain unread message are highlighted in the folder display. Pull down the main Help menu and select \fIColor Legend\fP to display a key to the highlights for your display. The highlighting is covered in more detail later in the \fBexmh-use\fP man page. The \fBexmh-custom\fP man page tells how you can control the highlighting yourself. .PP \fBStatus Line\fP. Just below the table of contents is the status line. This has two parts. The left part shows the name of the folder and the message number for the current message, if any. The right part gives feedback about what \fIexmh\fP is doing. After it displays a message, the Subject component is displayed there. .PP \fBSubwindow Resize Diamond.\fP The black diamond to the right of the status line is used to change the size of the internal windows. Press the first mouse button on this target and a horizontal line appears. Drag it up and down to adjust the window sizes. Try dragging it all the way to the top and bottom of the exmh window to see how the mode changes to adjust different windows. .PP \fBMessage Buttons\fP The bottom row of buttons are for operations that apply to the current message. Several of these operations will be introduced in this man page. The right hand button labeled More... brings up a menu with several more advanced message operations. .PP \fIHint:\fP Many of these message operations have keyboard shortcuts that make it easy to use \fIexmh\fP with your hands on the keyboard. Some of the short-cuts are introduced in this man page, and all of them are listed in the \fBexmh-use\fP man page. .PP \fBMessage Display\fP. The bottom subwindow displays the current message, if any. Some of the less interesting mail headers start out scrolled off the top of this window. .SH SENDING MAIL .PP A good way to test things out is to send a message to yourself. Here are the steps you take to do that: .PP 1. Click the Send button, which is in the Message buttons in the bottom group. A new window will open that contains the template for your message. The built-in editor, which is called \fIsedit\fP, will start out with the insert cursor positioned at the end of the first empty header line. Enter your user name after the To: header. If you want to send the message to more than one person, use a comma to separate the names. .PP 2. Position the insert cursor on the next header line. You can do this a few different ways. The most direct way is to click the left mouse button where you want the cursor to be. There are keyboard shortcuts, too. If you press the editor will take you to the end of the next header line. You can also use the arrow keys or some emacs-like bindings to move the cursor. goes to the next line, moves the cursor forward a character. moves up a line, and moves back a character. The \fISimple Edit\fP menu entry shows you all the keybindings. .PP 3. The next header is the Cc: line. People listed in the Cc: line get a "courtesy" (or "carbon") copy of the message. By convention, the message is primarily for the people listed in the To: component, and the people in the Cc: component are getting the message "for information." In this case, you can leave the Cc: component empty. .PP Move the insert cursor to the Subject: line and enter a Subject. The people that receive your message will get an idea of what the message is about from the subject, so take a moment to think of a good one. For this test, you can type something like "exmh test message". .PP 4. Make sure the headers are OK. In particular, make sure there are no blank lines in the headers. The mail system treats a blank line as meaning "end-of-headers", so you don't want to prematurely end the header section. If you have a blank line, position the insert cursor on it and use Backspace to remove the empty line. .PP Position the cursor at the start of the message body. You can use the mouse for this, or you can press twice quickly and the editor will position the cursor correctly. When using the default MH message templates, this will be right after the line of all dashes. .PP 5. Type in your message. When you type in a long message, the lines will wrap automatically at word boundaries. To get a blank line for paragraph boundaries, press . The built-in editor supports several editing commands that are based on the GNU emacs key bindings. If you select the \fISimple Edit\fP menu entry under the main Bindings menu, you will bring up a dialog that lets you view and edit the key bindings. .PP 6. If you are happy with the message, you send it by pressing the Send button at the top-right corner of the window. The Send button will turn grey, and the window will disappear once the message has been sent successfully. .PP If you do not want to send the message, press the Abort button instead. If you want to save the message draft and continue to work on it later, press the Save&Quit button. Working on a saved draft message is described in the \fBexmh-use\fP man page. .PP Send yourself a few messages, or have a friend send you a few test messages. You will use these test messages to practice moving around in a folder and deleting messages. Make one of the messages pretty long so you can practice scrolling through it. .PP Finally, try sending mh-mime-sample@online.ora.com a message. This addresses a program that will return a MIME message to you. Just put this address in the To field with anything as the message body and subject. Reading this message will be described below. .SH MOUSING AROUND .PP The selection is dragged out with the left mouse button. You can modify the selection by holding the Shift key while pressing the left button. A double-click begins a word-oriented selection, and a triple-click begins a line-oriented selection. If you drag a selection off the bottom or top of a window the text will be scrolled automatically and the selection will be extended. .PP Paste is done with the middle mouse button. .I The current insert point is used, not the point at which you middle-click. If you drag the middle mouse button, then the window is scrolled instead as described below. There is also a key-binding for paste, which is . Use or the key to delete the selection. .PP The middle mouse button is used for "drag-scrolling". To scroll, simply press the middle mouse button over the text and drag the text. If you press the Shift key, the scrolling is faster. Drag-scrolling works in the text widgets, for vertical scrolling, and the one-line entry widgets, for horizontal scrolling. The text widgets are used to display the folder contents and the current message. The entry widgets are used in various dialogs in order to enter values. You can change the scrolling button to the right button or to only work with shift-middle. Set this up in the Simple Edit Bindings... dialog. .PP Buttons and menus are also sensitive to which mouse button is pressed. Only the left button activates a button, and it is the event that is important. If you accidentally move the mouse off of the button as you release it, nothing will happen. Don't worry, the wrong button will not be invoked. .PP Press the left button over a menu button to pull down a menu. Most of the menus in \fIexmh\fP are distinguished with a "..." in their label, e.g. "More...". The menu will go away when the button is released. Release the mouse button off the menu if you do not want to invoke any menu item. (In some versions of Tk, the middle button will "tear off" a Tk menu. This is quite handy if you use the menu often. To get the menu to go away, you must click the left button over the menu button. This will reattach the menu to the menu button, and another left click will make the menu go away. In the latest versions of Tk, the first menu entry is a dashed line that invokes this tear-off operation.) .SH GETTING NEW MAIL .PP By now you should have some new mail waiting. Press the Inc button from the middle set of buttons that do Folder operations. This will transfer messages from your system spool file into your inbox folder. You will hear an audible cue if there was new mail, and the table of contents will be updated to reflect the new messages in your inbox. New messages will be underlined (on a monochrome screen), or blue (on a color screen), to indicate that you have not read them yet. .PP To view the new message, click on its line in the table of contents, or press the Next button in the bottom group of buttons. The message will be displayed in the bottom subwindow, and the line in the table of contents will be highlighted to remind you which message is being displayed. .PP To view the next message, click the Next button. The keyboard shortcut for this is the 'n' key. .PP The view the previous message, click the Prev button. The keyboard shortcut for this is the 'p' key. .PP \fBScrolling through messages\fP. If you get a message that is too long to fit into the message window, then the scrollbar will change its appearance to indicate how much text is displayed. The scrollbar is Motif-like. You can click on the arrows at either end to go up and down one line. If you click above or below the elevator box you go up and down one page. You can drag the elevator box to scroll, too. .PP You can also scroll text windows in \fIexmh\fP by dragging with the middle mouse button. Press the middle button over the text area, not the scrollbar, and hold it down while you move the mouse up or down. If you hold the shift key at the same time, the scrolling is faster. This works in the folder Table of Contents window, too. .PP \fIHint\fP. The space bar is a keyboard short-cut that does a combination of scrolling and advancing to the next message. If the message is long, then space will scroll by one screen. Once you are at the end of the message, space will advance to the next message, just like the 'n' key. You can use the BackSpace key to scroll back through a message. .SH READING MIME MESSAGES .PP By now you should have also received the sample MIME message from mh-mime-sample@online.ora.com. The MIME message has three parts to it, and these are numbered and labeled in the display. The first part is a multipart/alternative content, which means there are a few different ways to view the content. This is indicated by the message under the heading \fB1.\fP that there are alternative views of the following content. \fIExmh\fP will go ahead and display what it thinks is the best alternative, and you see the text/enriched content displayed in part \fB1.2\fP. If you want to see the other alternatives, then you can press the right button over section 1 to get a popup menu with some choices. .PP The next two parts are an audio clip and a picture in GIF format. The audio clip is handled directly by exmh, and it displays two active text buttons labeled "Play attached audio" and "Save audio file". Click on either of these with the left mouse button. The part corresponding to the image displays a message about what the type is, and suggests that you press the right mouse button to display a menu. You can always press the right button to get a MIME menu that has type-specific options for parts of your message. If you press the right button over part \fB2.\fP, then the popup menu will offer you these choices: .DS Decode part as MIME Save Hello from the author... View using mailcap rule... Pass an audio fragment to metamail... .DE The first item is a checkbox menu item that lets you view the raw content if you want to. The Save... menu entry displays a file selection box so you can choose a non-temporary file to store the content. This same function is available through the text button, but not all MIME parts displays buttons like this. The next two entries should result in the same thing. They use the mailcap specifications to run another program that displays the content. In the first case, View using mailcap rule..., \fIexmh\fP runs the program directly. In the other case, Pass to metamail..., the \fImetamail\fP program is run first, and it decodes the mailcap file and runs the external program. Again, the text button labeled "Play attached audio" also plays the audio. .SH REPLYING TO MAIL .PP Select one of the messages from your friend that you'd like to answer. Press the left button over the Reply... menu button. A menu with a few entries will be displayed. Select the \fIReply to sender\fP menu entry by dragging the mouse down to that entry and letting up over it. The menu entry has a in it, which means that you could also press the 'r' key to invoke this function. .PP This time the built-in editor will open a window with a message that is partly filled in. All the headers are initialized based on the header components from the original message. The built-in editor will automatically position the cursor at the beginning of the message body. You can enter your reply message like you did with the previous messages. You should also double-check the header components. In this case, add yourself to the Cc: component so you will get a copy of the reply message. When you are done, press the Send button in the editor window to send the message. .PP There are a number of ways to control the format of your reply messages. The MH \fIrepl\fP command has several formatting options, and because \fIexmh\fP uses \fIrepl\fP to set up the reply message, you can customize your reply format. \fIExmh\fP lets you define several variations on reply and add them to the Reply... menu. This is described in the \fBexmh-custom\fP man page. .PP It should not take long for you to get the copy of the reply message. Wait a minute or so and press the Inc button. The keyboard short-cut for Inc is the 'i' key. .SH SELECTING MESSAGES .PP Before we go on to more things you can do with messages, we need to talk about selecting multiple messages at once. Several of the message operations in \fIexmh\fP can operate on a set of messages. You can manually select multiple messages by using the mouse, or you can select messages based on their content. .PP \fBUsing the Mouse\fP. To select messages with the mouse, press the left button and then drag out a selection. This will select a contiguous range of messages. If the messages you want to select are not so nicely organized, you can make a disjoint selection by holding down the Shift key while making your selection. This adds new messages to the selection. If you shift-click on a message that is already selected, then it becomes unselected. If you need to select a lot of messages, simply drag the mouse off the top or bottom of the window. It will be scrolled automatically and the selection will be extended. .SH SEARCHING .PP The Search... menu has several operations for finding messages and finding text within a message. There is also a help entry that explains searching in more detail. If you select "Find in message body" or "Find in table of contents" a small search dialog appears. Enter the search string and use the Next or Prev buttons to find the next match. When you are searching over the table of contents, you can select All to select all matching messages. .PP The other way to search a folder is with "Pick by attributes". The MH pick program is used to search the current folder for messages that match mail headers like From or Subject. You can build up boolean expressions among search criteria. This is a much more general search mechanism than the "Find in table of contents" operation. .PP Get started in the Pick dialog by pressing the "Choose pick attribute" button. A menu of attribute types appears, including the Subject, From, To, and Cc header components. You can type a regular expression pattern in these entries to search for messages that have a matching header component. .PP The Before and After attributes are dates. You can find all messages before or after a given date by using these fields. You can specify dates as mm/dd/yy. Be sure to include the year. Dates can also be keywords like "today", "yesterday", "tomorrow", and any day of the week ("Sunday", "Monday", and so on.) .PP The Search attribute is used to search for something in the body of a message. This will run little slower because \fIpick\fP must read through all of your messages, not just their headers. .PP If you select more than one attribute, \fIpick\fP finds messages that match all the criteria. In other words, it does the logical \fIand\fP of the search criteria. If you want to search for this \fIor\fP that, then you need to press the Or button in the dialog. This adds another set of fields to the dialog, and pick will search for everything that matches the first set \fIor\fP matches the second set. .PP The "Add to Sel" checkbutton should be set \fIbefore\fP you do the search. This controls whether or not the selected messages are added to any existing selection. .PP Finally, use the "Pick" button to do the search. Once the search has completed you can perform a few operations on the selection. You can delete and refile messages as described later. You can also display a new table of contents that only contains the selected messages. Use the "New FTOC" button for this. You can also clear the unseen state of the messages with the "Mark Seen" button. .PP The "Clear" button resets the fields. .PP The two entries in the dialog are used to control MH sequences. The only sequence exmh really supports well is the "unseen" sequence, although you can define up to 10 sequences in each folder. .PP If you use New FTOC to get a new scan listing, it would be better if it appeared in a new window, but currently it replaces the table of contents. You can move around and manipulate messages in this table of contents. However, if you do another pick, it will only find things in this limited table of contents, not the whole folder. (Yes, this is a bug.) Use the Rescan Folder menu entry in the folder More... menu to get a complete folder listing. .SH FORWARDING MESSAGES .PP If you want to send someone a copy of a message or messages that you have received, use the Forward message operation. Select the messages as described in the previous section, then press the Forward button. The keyboard short-cut for forward is the 'f' key. .PP The message template will have a copy of the selected messages. You fill in the headers, and you can also add a short message before the start of the forwarded messages. When you are done, press Send to forward the messages. .SH DELETING MESSAGES .PP After you have read a message, you might want to remove it to keep your mail folders tidy. \fIExmh\fP uses two steps to remove mail. In the first step you \fImark\fP a message as being deleted. In the second step you \fIcommit\fP the operations on all marked messages. It turns out that delete just renames your message files. They will survive until you get another message by the same number and remove it, too. In addition, exmh has a "Purge Folder" operation that removes these renamed files if they are more than a week old. .PP The Delete operation applies to the current message, or you can also select a range of messages by dragging out a selection in the table of contents. You can delete the current message(s) by pressing the Delete button. The keyboard short-cut is the 'd' key. The deleted message(s) will be highlighted after the delete operation so you can easily see the state of the message. On a monochrome screen, a cross hatching will be drawn through the table of contents line for the message. On a color screen, the table of contents line will get a dark grey background. .PP After you mark a message for delete, you are automatically advanced to the next message. This makes it easy to go through your folder and clean it up. Click 'd' to delete, or click 'n' to leave it alone. .PP \fIHint\fP. If you are really in a hurry, use 'D' and 'N' as your keyboard short-cuts. This prevents the next message from being displayed, which can be slow for complex multi-media messages. .PP When you are ready to commit the pending delete actions, press the Commit button. The keyboard shortcut for commit is . .PP If you decide you do not want to delete a message you can unmark it. Use the \fIUnmark (Undo)\fP menu entry that is under the message More... menu. The unmark operation applies to the current message or messages, so you have to select the messages to unmark first. The keyboard short-cut for unmark is 'u'. .PP \fIHint\fP. The minus, '-', keyboard shortcut takes you to the previous message, even if it has been marked for delete. Ordinarily the Prev operation, and the 'p' short-cut for it, will skip over marked messages. .SH LEAVING EXMH .PP Press the Quit button to leave exmh. It will take a few moments to close down because it saves some state information before quitting. The Quit button will grey out after you click it, and you will see a few status messages as it shuts itself down. .SH PREFERENCES .PP Try out the Preferences by turning off the folder cache. This just takes up display space if you don't have many folders. If you have lots of nested folders, though, you might even want to make this display bigger! .PP Click the Preference button, which brings up a dialog that has buttons for several of the modules that make up \fIexmh\fP. Click on the Folder Cache button to bring up the preference items that control the folder cache. In this case there are just two items: the number of lines of labels in the cache, and the names of folders that are always in the cache. Click in the first field and backspace over the default value of 1. Type in 0 instead, and press . Voila! The folder cache disappears. .PP If you like this setting, press Save on the main Preference dialog and your changes will be saved to a file named ~/.exmh-defaults. Press Reset if you want to undo your changes. You should be a little careful here, because you are allowed to Dismiss the preference dialog without saving. .PP Another useful preference item to set is under Background Processing. You can arrange for \fIexmh\fP to periodically run \fIinc\fP so your messages are automatically transferred into your inbox. The advantage of doing this is that the folder label highlighting works best this way. Unfortunately, \fIexmh\fP does not give you any visual clues when mail is only waiting in your system spool file. .PP More details about the Preferences dialog are given in the \fBexmh-use\fP man page, and an overview of the various preference sections is given in the \fBexmh-custom\fP man page.. .SH "WHAT IS MH MAIL?" .PP MH is a collection of UNIX programs that store, manipulate, and display your mail. MH originated from RAND, and it is now in the public domain. Exmh uses these programs to do all the hard work, while it concentrates on the user interface. .PP You can use the MH programs to read your mail. Run them from the UNIX command line like you would cd, ls, cc, or make. They are useful when you are connecting over a slow line or cannot run exmh for some other reason. For more details, there are individual man pages for each MH program, plus one overview man page called MH. Below is a short summary of the main MH programs used by exmh. .IP folder Query or set the current folder. .IP inc Incorporate mail from your system spool file into your folders. .IP scan Display a listing of a mail folder. .IP show Display a mail message. .IP next Display the next mail message. (Exmh doesn't actually run this.) .IP prev Display the previous mail message. (Exmh doesn't actually run this.) .IP rmm Delete a mail message. .IP refile Move a message into another mail folder. .IP repl Reply to a mail message .IP forw Forward one or more mail messages. .IP comp Compose a new mail message. .PP MH keeps track of the current folder and the current message in between uses of these MH programs. For example: .DS % scan +inbox unseen 1713 04/14 foote.PARC@xerox. Have you started blasting cdroms yet?< .SH THANKS To Xerox PARC/CSL, for supporting this work initially, to Sun Microsystems Laboratories for continuing the support, and to all the exmh users that contributed ideas and code. exmh-2.9.0/exmh-async0000755000170700017070000000152213370473410014021 0ustar valdisvaldis#!/usr/bin/wish -f # # async editor frontend for exmh # Arg1: invoking interpreter's name (from [winfo name .]) # Arg2-end: editor command, including pathname # LastArg: pathname of draft message # package require Tk wm withdraw . # simple argv cracking set exmh [lindex $argv 0] set editorCmd [lrange $argv 1 end] set draftpath [lindex $argv [expr {[llength $argv] - 1}]] set draftm [file tail $draftpath] send $exmh [list Edit_Ident [winfo name .]] # Used to do a split/join on $editorCmd to allow quoted -geom arguments. # But that totally screws some arguments, like # exmh-async gvim -c {cal SetSyn("mail")} # other interesting cases are # exmh-async xterm -geom +0+0 -e vi {+/^[-]*$} if [catch {eval exec $editorCmd} err] { send $exmh [list Exmh_Status "exmh-async: editor failed: $err" purple] } send $exmh EditDialog $draftm exit 0 exmh-2.9.0/exmh-bg.MASTER0000755000170700017070000001301213201227060014252 0ustar valdisvaldis#!wish -f # # Background processing script for exmh. # This does stuff and then sends messages to the background module # in the main exmh application. In particular, the time-consuming things # like running inc are done here instead of the main-line. # # Copyright (c) 1993-8 Brent Welch # Copyright (c) 1993 Xerox Corporation. # Copyright (c) 1996-8 Sun Microsystems # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # and Sun Microsystems # make no warranty about the software, its performance or its conformity to # any specification. #CONFIGURATION #END CONFIGURATION package require Tk wm withdraw . if {$argc < 3} { puts stderr "exmh-bg requires some arguments:" puts stderr "Usage: exmh-bg interpName libDirectory mh_path" exit 1 } set exmh(interp) [lindex $argv 0] set exmh(library) [lindex $argv 1] set mh_path [lindex $argv 2] proc auto_path_update { path } { # Add library directories to the auto_path, # ensuring that later paths have precedence # and that function override works global auto_path if [file exists $path/tclIndex] { set auto_path "$path $auto_path" # auto_reset call eliminated } } auto_path_update $exmh(library) # Support per-user directory containing .tcl files. foreach exmh(userLibrary) [list [glob ~]/.exmh/lib [glob ~]/.tk/exmh] { if {[file exists [file join $exmh(userLibrary) tclIndex]]} { auto_path_update $exmh(userLibrary) ;# library for new modules break } } # Set up environment variables Env_Init proc Exmh_Status { string args } { # Just a stub version until we rendez-vous with the front end. # If the userLibrary Preferences_Add is done after we define the # full blown Exmh_Status, then the auto_path_update and its # auto_reset seem to result in the Exmh_Status from main.tcl # being faulted in from the library. catch {puts stderr "exmh-bg: $string"} } # Tk 4.0b3 bogosity if [catch {tk colormodel .}] { rename tk tk-orig proc tk { option args } { switch -- $option { colormodel { if {[winfo depth $args] > 4} { return color } else { return monochrome } } default { return [eval {tk-orig $option} $args] } } } } Preferences_Init ~/.exmh/exmh-defaults $exmh(library)/app-defaults if [catch {User_Init} err] { catch {puts stderr "User_Init: $err"} } proc Exmh_Debug { args } { global exmh if [info exists exmh(pid)] { BgRPC Exmh_Debug exmh-bg $args } else { catch {puts stderr "exmh-bg $args"} } } # Register ourselves with the UI proc BgRegister { exmhInterp } { global exmh set exmh(sendErrors) 0 if {[catch { send $exmhInterp [list Background_Register [winfo name .] [pid]] } alist] == 0} { # set bg parameters returned as a result of registration foreach pair $alist { set _var [lindex $pair 0] set _val [lindex $pair 1] uplevel #0 [list set $_var $_val] } return 1 } else { if [regexp {no registered interpreter} $alist] { catch {puts stderr "exmh-bg lost UI - exiting."} exit } catch {puts stderr "BgRegister $alist"} return 0 } } set ok 0 foreach try {1 2 3 4 5} { set ok [BgRegister $exmh(interp)] if {$ok} { break } exec sleep [expr $try*$try] } if {! $ok} { catch { puts stderr \ "exmh-bg cannot rendez-vous with UI - exiting. Usually this is because Tk send is not working. Check the notes under Frequently Asked Questions #4a and #4b. You can find this under the Help menu." } exit 1 } proc Exmh_Status { string {color black} } { global exmh if [info exists exmh(instatus)] { catch {puts stderr "exmh-bg: $string"} return } set exmh(instatus) 1 # All this code to evaluate something that should be evaluated in # the main Exmh interpreter if BgRPC suceeds - and if we call our stub # Exmh_Status the value is ignored anyhow. # if ![info exists exmh(c_st_bg_msgs)] { # if {[tk colormodel .] == "color"} { # set exmh(c_st_bg_msgs) [option get . c_st_bg_msgs {}] # if {$exmh(c_st_bg_msgs) == {}} { # set exmh(c_st_bg_msgs) [option get . bgMsgColor {}] # if {$exmh(c_st_bg_msgs) != {}} { # puts stderr "Warning: old resource bgMsgColor, changed to c_st_bg_msgs" # } else { # set exmh(c_st_bg_msgs) "medium sea green" # } # } # } else { # set exmh(c_st_bg_msgs) [option get . c_st_bg_msgs {}] # if {$exmh(c_st_bg_msgs) == {}} {set exmh(c_st_bg_msgs) black} # if {$exmh(c_st_bg_msgs) != "white" && $exmh(c_st_bg_msgs) != "black"} { # set exmh(c_st_bg_msgs) black # } # } # } BgRPC Exmh_Status $string background unset exmh(instatus) } proc Exmhbg_Done {interp} { # Die asynchronously so the front-end gets a response # to its send request first. Set a dead flag so BgRPC # doesn't try to talk to the front end global exmh if {$exmh(interp) == $interp} { set exmh(dead) 1 after 1 { catch {Audit_CheckPoint} destroy . } } } # Now do things periodically. We fault in routines from # the regular library of exmh procedures. The Inc'ing # routines have been tweaked to understand the (possible) # split into a separate process, and the above hack to # Exmh_Status handles the simpler cases. Mh_Init Inc_Init Ftoc_Init ;# Need ftoc(scanWidth) Flist_Init Seq_Init ;# Need seqwin(nevershow) Post_Init set busy(style) none Background_Init Background_DoPeriodic exmh-2.9.0/exmh0000755000170700017070000001102613370473410012706 0ustar valdisvaldis#!/usr/bin/wish -f # # TK interface to the MH Mail utility # Brent Welch # Original version by # # Copyright (c) 1993-8 Brent Welch # Copyright (c) 1993-5 Xerox Corporation. # Copyright (c) 1996-8 Sun Microsystems # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and Xerox Corporation # and Sun Microsystems # make no warranty about the software, its performance or its conformity to # any specification. # The following lines are patched by exmh.install #CONFIGURATION set wish /usr/bin/wish set exmh(version) {version 2.9.0 11/07/2018} set exmh(name) exmh set exmh(maintainer) valdis.kletnieks@vt.edu set mh_path /usr/local/bin set exmh(slocal) /usr/local/libexec/nmh/slocal set mime(dir) /usr/bin set mailcap_default /etc/mailcap set mimetypes_default /etc/mime.types set exmh(expect) /usr/bin/expect set exmh(expectk) /usr/local/bin/expectk set faces(dir) /usr/local/faces/faces set faces(set,user) {local users usenix misc} set faces(set,unknown) {domains unknown} set faces(set,news) news set faces(defaultDomain) eng.sun.com set faces(suffix) {xpm gif xbm} set pgp(pgp,path) /usr/local/bin set pgp(pgp5,path) /usr/local/bin set pgp(gpg,path) /usr/bin set pgp(pgp6,path) /usr/local/bin set glimpse(path) /usr/local/bin set sound(cmd) {/usr/demo/SOUND/play -v 38} set exmh(library) /usr/local/lib/exmh-2.9.0 set install(dir,bin) /usr/local/bin set install(dir,man) /usr/local/man/manl set install(dir,lib) /usr/local/lib/exmh-2.9.0 #END CONFIGURATION package require Tk if {$tcl_version < 8.5} { error "Tcl 8.5 or higher required." exit 1 } # Do this so popups related to user initialization # appear all alone. wm withdraw . # fonts in tk8.5: short aliases like don't work properly anymore # (confusion with the font face stuff) # recreate the common fallback "fixed" as a copy of TkFixedFont eval font create fixed [font configure TkFixedFont] proc auto_path_update { path } { # Add library directories to the auto_path, # ensuring that later paths have precedence # and that function override works global auto_path tk_version if [file exists $path/tclIndex] { set auto_path "$path $auto_path" # Used to have an "auto_reset" here, but that has the bad # side effect of causing Tk's entry.tcl and text.tcl files # to reload and redefine top-level Entry and Text bindings # that we change in seditBind.tcl. # catch {auto_reset} ;# Needed for function override } } auto_path_update $exmh(library) if ![file exists $exmh(library)/tclIndex] { if [file exists ./lib/tclIndex] { puts stderr "Warning, using local script library, ./lib" set exmh(library) ./lib } } # Support per-user directory containing .tcl files. # This was originally the ~/.tk/exmh directory, # but then files migrated into ~/.exmh so # a lib subdirectory there is cleaner foreach exmh(userLibrary) [list [glob ~]/.exmh/lib [glob ~]/.tk/exmh] { if {[file exists [file join $exmh(userLibrary) tclIndex]]} { auto_path_update $exmh(userLibrary) ;# library for new modules break } } # Fall through with ~/.tk/exmh as the default because there # are other places in the code that assume exmh(userLibrary) is defined # Set up the environment if {[catch { Env_Init } err]} { puts stderr "Error running Env_Init: $err" puts stderr "This usually means exmh isn't installed right" puts stderr "Check the main exmh script for the CONFIGURATION section" puts stderr "and make sure exmh(library) is a valid absolute pathname" exit 1 } # For WindowMaker, http://www.inf.ufrgs.br/~kojima/wmaker/ wm group . . # For session managers wm command . "$argv0 $argv" catch {wm client . "[exec hostname]"} catch { . configure -cursor left_ptr } # modified by k.furukawa, jul.1994. for kanji # this piece of code enables japanese kanji display if you use # tk-jp extension and JIS code. if you use EUC for MH processing # codes, you may replace JIS with EUC and you may need more works. if {[info commands kanji] == "kanji"} { kanji internalCode JIS option add *Text.Font a14 } # Ensure the user is in a writable directory for @ links if {[string match /* $exmh(library)] && [string match /* $argv0]} { # Don't go anywhere when testing cd } # The rest of the application is defined by routines in the exmh library # The after 1 trick is to ensure we get the built-in error handler. after 1 {Exmh} exmh-2.9.0/exmh-strip.MASTER0000755000170700017070000003203013201227060015024 0ustar valdisvaldis#!wish #(Note - you should also be able to use tclsh with this.) # # Utility to strip out attachments from MIME messages. # They are replaced with references to the external files. # # You must supply the input message destination directory on the command line. # This does not handle nested multiparts correctly. So, if you # forward a message with attachments, the message/rfc822 layer # outside the multipart/mixed will foil it. # # The original message is put into a "strip_backup" folder. It # is replaced with a message containing message/external-body parts # that reference the saved attachment. # # This script is invoked from a procedure like the following, # which is now build into mime.tcl. There is also a MIME preference # to choose the save directory, which is hardwired in this example. proc Mime_SaveAttachments {} { global msg exec [glob ~/bin/exmh-strip] $msg(path) [glob ~/doc] Msg_ShowCurrent } # You can also use this from a small shell script, e.g.: if {0} { #!/bin/csh tclsh8.3 ~/bin/exmh-strip `mhpath cur` ~/doc ls -lt ~/doc | head -2 } # Here are some resources for your exmh-defaults that add this to a new menu. # *Mops.umenulist: repl2 # *Mops.repl2.text: Welch # *Mops.repl2.m.entrylist: save sep # *Mops.repl2.m.t_sep: separator # *Mops.repl2.m.l_save: Save Attachments # *Mops.repl2.m.c_save: Save_Attachments # # Copyright (c) 2001 Brent Welch # Use and copying of this software and preparation of derivative works based # upon this software are permitted. Any distribution of this software or # derivative works must comply with all applicable United States export # control laws. This software is made available AS IS, and no one # makes any arranty about the software, its performance or its conformity to # any specification. #CONFIGURATION #END CONFIGURATION if {[catch {wm withdraw .}]} { # Stub out stuff when not running under wish proc option {args} {return ""} proc winfo {args} {return ""} set pref(panes) "" set exmh(userLibrary) "" } if {$argc < 2} { puts stderr "exmh-strip requires some arguments:" puts stderr "Usage: exmh-strip msg_path doc_directory" exit 1 } set msg_path [lindex $argv 0] set doc_directory [lindex $argv 1] set uniq 0 ;# for content-ID generation proc auto_path_update { path } { # Add library directories to the auto_path, # ensuring that later paths have precedence # and that function override works global auto_path if [file exists $path/tclIndex] { set auto_path "$path $auto_path" catch {auto_reset} ;# Needed for per-user override, but breaks w/ TCLX } } auto_path_update $exmh(library) # Set up environment variables Env_Init proc Exmh_Status { string args } { catch {puts stdout $string} } proc Exmh_Debug { args } { switch -glob -- $args { Pref_Add* { return } {*MH anno*} { return } {*Unable to load Img*} { return } MimeTypes* { return } default { catch {puts stdout [join $args]} } } } # We fault in routines from the regular library of exmh procedures. # We shouldn't depend on per-user code, so just hardwire userLibrary set exmh(userLibrary) ~/.exmh Preferences_Init "~/.exmh/exmh-defaults" "$exmh(library)/app-defaults" Mh_Init Mime_Init Pgp_Base_Init proc dummy_tk_window {args} { # Ignore everything done to the window } # Procedure to strip out attachments. # Unfortunately we have to rip out various code sections # from mime.tcl proc Mime_Strip {fileName} { global mime mimeHdr # Stuff from MsgShowInText set part 0 set subpart 1 set mimeHdr($part=$subpart,hdr,cur) {} set mimeHdr($part=$subpart,hdr,from) {} set mimeHdr($part=$subpart,hdr,date) {} set mimeHdr($part=$subpart,hdr,subject) {} set mimeHdr($part=$subpart,hdr,x-face) {} set mimeHdr($part=$subpart,hdr,x-image-url) {} set mimeHdr($part=$subpart,hdr,newsgroups) {} set mimeHdr($part=$subpart,fullHeaders) $mime(fullHeaders) set mimeHdr($part=$subpart,yview) 1.0 set mimeHdr($part,decode) 1 set mimeHdr($part,file) $fileName set mimeHdr($part,rawfile) $fileName #set mimeHdr($part,color) [lindex [$win configure -background] 4] set mimeHdr($part,color) "" set mimeHdr($part,type) message/rfc822 set mimeHdr($part,encoding) 7bit set mimeHdr($part,hdr,content-type) message/rfc822 set mimeHdr($part,HeaderSize) 0 set mimeHdr($part,display) 1 global mimeFont if ![info exists mimeFont(default)] { set mimeFont(title) "" set mimeFont(note) "" set mimeFont(default) "" } set partTag [MimeLabel $part part] set defaultTag [MimeLabel $part=1 part] # From MimeSetPartVars if [catch {open $fileName r} fileIO] { Exmh_Status "Cannot open body $fileName: $fileIO" set mimeHdr($part,numParts) 0 return 0 } # Open shadow output for new version of stipped message if [catch {open ${fileName}.strip w} out] { Exmh_Status "Cannot open body ${fileName}.strip: $out" set mimeHdr($part,numParts) 0 close $fileIO return 0 } set result [MimeParseSingle $part $fileIO $out] MimeClose $fileIO close $out if {!$result} { # No attachements found file delete ${fileName}.strip } else { file mkdir [file join [exec mhpath +] strip_backup] file rename ${fileName} [exec mhpath +strip_backup new] file rename ${fileName}.strip ${fileName} } return $result } # Modified version of MimeParseSingle from lib/mime.tcl proc MimeParseSingle {part fileIO out} { global mimeHdr mime miscRE msg global doc_directory set mimeHdr($part=1,color) $mimeHdr($part,color) set part $part=1 set mimeHdr($part,hdrs) {} set uniq 0 # Skip any blank lines or "ugly uucp-style From_ lines" at the frontend. while {([set numBytes [gets $fileIO line]] == 0) || [regexp {^(>?From |[ ]+$)} $line]} { puts $out $line } puts $out $line # Parse headers set headers "" if [regexp {^([^: ]+):} $line] { while {$numBytes > 0} { if {[regexp -- {^-*$} $line]} { # Drafts-folder message break } if ![regexp {^[ ]} $line] { if [regexp -indices {^([^:]+):} $line match hdr] { set cur [string tolower \ [eval {string range $line} $hdr]] if {[lsearch $mimeHdr($part,hdrs) $cur] >= 0} { # Duplicate header set cur :$uniq:$cur incr uniq } set mimeHdr($part,hdr,$cur) \ [string trim \ [string range $line \ [expr [lindex $match 1]+1] end]] lappend mimeHdr($part,hdrs) $cur } } elseif [regexp -indices {^[ ]+} $line match] { append mimeHdr($part,hdr,$cur) \n$line } set numBytes [gets $fileIO line] append headers $line\n } if [catch {set mimeHdr($part,hdr,content-type)} contentType] { set contentType text/plain } if [catch {set mimeHdr($part,hdr,content-transfer-encoding)} encoding] { set encoding 7bit } if {[string compare $contentType X-sun-attachment] == 0} { set contentType "multipart/x-sun-attachment; boundary=--------" set mimeHdr(0=1,hdr,mime-version) x-sun-attachment } set encoding [string trim [string tolower $encoding] \ \" ] set type [MimeHeader $part $contentType $encoding] if {[string compare $part "0=1"] == 0} { set mimeHdr($part,decode) \ [expr {$mime(enabled) && [info exists mimeHdr(0=1,hdr,content-type)]}] } } else { # Weird no header case Exmh_Status "no headers" return 0 } if {$numBytes >= 0} { if {[string match multipart/* $type]} { # Look through parts for attachements to strip puts $out $headers return [MimeChopPart $part $fileIO $out] } elseif {![regexp {^(text|message)/.*} $type]} { # Skip text and message types set body [read $fileIO] return [MimeStripPart $part $headers $body $out] } } return 0 } proc MimeStripPart {part headers body out} { global mimeHdr doc_directory uniq # Grab a hint for the filename from the part headers # The param,* are parameters to the Content-Type header # and other headers, especially Content-Disposition # The hdr,* are other headers. foreach hint { param,filename hdr,content-description param,name } { if {[info exist mimeHdr($part,$hint)]} { set path $mimeHdr($part,$hint) break } } if {![info exist path]} { # Not an interesting thing - e.g., "vcard" junk or text return 0 } set path [file tail $path] set path [string trim $path] if {[regexp {^\|} $path]} { catch {puts stderr "Bad filename $path"} exit 1 } set path [file join $doc_directory $path] if {[file exists $path]} { catch {puts stderr "$path exists"} exit 1 } if {[catch {open $path w} newout]} { # Cannot save to suggested file name Exmh_Debug "exmh-strip:MimeStripPart can't open $newout" return 0 } if {[MimeSavePart $part $body $out $newout]} { # Successfully stripped the part - now whack the headers regexp -nocase {content-type[^\n]+} $headers oldtype regsub -nocase {content-transfer-encoding[^\n]+\n} $headers \ {} headers regsub -nocase {content-type.+\n([^\t\n])} $headers \ "Content-Type: message/external-body; name=\"$mimeHdr($part,param,filename)\"; access-type=local-file; directory=\"$doc_directory\"; \\1" headers # Output new headers and stub body puts -nonewline $out $headers\n puts $out $oldtype puts $out "Content-ID: exmh-strip-[clock format [clock seconds] \ -format {%Y-%m-%d-%H-%M-%S}]-[incr uniq]" close $newout return 1 } close $newout return 0 } proc MimeSavePart {part body out newout} { global mimeHdr doc_directory global mime switch -regexp -- $mimeHdr($part,encoding) { (8|7)bit { puts -nonewline $newout $body } base64 { if {[info exist mime(encode)]} { exec $mime(encode) -u -b >@ $newout << $body } else { puts -nonewline $newout [Base64_Decode $body] } } quoted-printable { if {[info exist mime(encode)]} { exec $mime(encode) -u -q >@ $newout << $body } else { puts -nonewline $newout [mime::qp_decode $body] } } .*uue.* - default { # Punting on uuencoded and anything else weird. puts -nonewline $out $body return 0 } } return 1 } proc MimeChopPart {part fileIO out} { # Chop up the parts at this level global mimeHdr if [catch {set mimeHdr($part,param,boundary)} boundary] { Exmh_Status "Invalid MIME Multipart" return 0 } # spaces in boundarys can cause line breaks - cc-mail trash regsub -all "\n *" $boundary { } boundary set type $mimeHdr($part,type) set mimeHdr($part,numParts) \ [MimeParseMulti $part $fileIO $boundary \ [expr {($type == "multipart/digest") ? \ "message/rfc822" : "text/plain"}] $out] } proc MimeParseMulti {part fileIO boundary defType out} { global mimeHdr mime set subpart 0 # Prolog while {([set numBytes [gets $fileIO line]] >= 0) && ([string compare --$boundary $line] != 0) && ([string compare --$boundary-- $line] != 0)} { puts $out $line } puts $out $line ;# Initial boundary while {($numBytes >= 0) && ([string compare --$boundary-- $line] != 0)} { incr subpart catch {unset contentType} # Header set headers "" while {([set numBytes [gets $fileIO line]] > 0) && ([string compare --$boundary-- $line] != 0) && ([string compare --$boundary $line] != 0) && (! [regexp -- {^-*$} $line])} { append headers $line\n if ![regexp {^[ ]} $line] { if [regexp -indices {^([^:]+):} $line match hdr] { set cur [string tolower \ [eval {string range $line} $hdr]] set mimeHdr($part=$subpart,hdr,$cur) \ [string trim \ [string range $line \ [expr [lindex $match 1]+1] end]] lappend mimeHdr($part=$subpart,hdrs) $cur } } elseif [regexp -indices {^[ ]+} $line match] { if {![info exists cur] || [regexp {^[ ]+$} $line]} { # No header! an error is about to occur... } append mimeHdr($part=$subpart,hdr,$cur) \n$line } } if {($numBytes >= 0) && ([string compare --$boundary-- $line] != 0)} { #MimeMapSunHeaders $tkw $part=$subpart if [catch {set mimeHdr($part=$subpart,hdr,content-type)} contentType] { set contentType $defType } if [catch {set mimeHdr($part=$subpart,hdr,content-transfer-encoding)} encoding] { set encoding 7bit } set encoding [string trim [string tolower $encoding] \ \" ] set type [MimeHeader $part=$subpart $contentType $encoding] # The following code *does not* handle nested multiparts. # Body set sep "" set body "" while {([set numBytes [gets $fileIO line]] >= 0) && ([string compare --$boundary $line] != 0) && ([string compare --$boundary-- $line] != 0)} { append body $sep$line set sep \n } catch {unset cur} if {[string match text* $type] || ![MimeStripPart $part=$subpart $headers $body $out]} { # Didn't strip it, have to restore original part puts $out $headers\n$body } puts $out $line ;# Another boundary } if ![info exists contentType] { # Empty body part incr subpart -1 } } return $subpart } Mime_Strip $msg_path exit 0 exmh-2.9.0/inc.expect.MASTER0000755000170700017070000000332713201227060014773 0ustar valdisvaldis#!/bin/sh # \ exec expect -f "$0" -- ${1+"$@"} # # Script to run inc and provide a password. # # When there is mail to incorporate, echo back only the message headers # for the FTOC. Otherwise, send back all text, for debug logging set timeout 60 gets stdin password # turn off echo so that password doesn't get echoed by tty driver set stty_init -echo eval spawn -noecho $argv log_user 0 # When .netrc exists, inc doesn't prompt for a password. After getting # a password one way or another, inc prints one of # Incorporating new mail into inbox...\r\n\r\n # inc: no mail to incorporate # # For the case of mail available, we want to drain the informational # line "Incorporating new mail" here, so it doesn't get sent back # as output and get stuck in the FTOC window, and proceed to the while # loop, below. # # If there's no mail, the informational message sent back, with exit 1, # so the message gets put into the debug log. # expect { -re "Password (.*):" { exp_send -- $password\n lappend incout $expect_out(buffer) $password\n expect { -re ".* new mail .*\n" {} eof { send_user $expect_out(buffer) exit 1 } timeout { send_user "timeout"; exit 1 } } } -re ".* new mail .*\n" {} eof { send_user $expect_out(buffer) exit 1 } timeout { send_user "timeout"; exit 1 } } # drain any empty line # echo back msg header for FTOC # if exit status of inc is non-zero (e.g., 1 for no mail), # echo back all accumulated text while {1} { expect { -re "^\[ \r\n]+$" {} -re ".*\n" { send_user $expect_out(buffer) } eof { if { [lindex [wait] 3] == 0 } { exit 0 } else { send_user $incout exit 1 } } } }