File: mime.tk

package info (click to toggle)
tkmail 4.0beta9-8.1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,444 kB
  • ctags: 923
  • sloc: tcl: 13,262; ansic: 6,998; makefile: 351; sh: 88; sed: 57
file content (770 lines) | stat: -rw-r--r-- 21,356 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
# mime.tk - support file for TkMail 
#	    commands for MIME operations
#
# $Header: /u/ra/raines/cvs/tk/tkmail2/mime.tk,v 1.3 1995/09/07 16:24:31 raines Exp $

proc mfv:mime-show-part {top tw fid msg mplist} {

  set part [lindex $mplist 0]
  set type [lindex $mplist 1]
  set subtype [lindex $mplist 2]
  set fulltype "$type/$subtype"

  if {$type == "multipart" || $fulltype == "message/rfc822"} {
    if {$subtype == "alternative"} {
      # TODO: for now take last subpart
      mfv:mime-show-part $top $tw $fid $msg [lindex [lindex $mplist 3] end]
    } else {
      foreach subpart [lindex $mplist 3] {
	mfv:mime-show-part $top $tw $fid $msg $subpart
      }
    }
    return
  }

  set enc [$fid message mimepart $msg encoding $part]

  if {$fulltype == "text/plain" || $fulltype == "message/delivery-status"} {
    if [catch {$tw insert insert [$fid message mimepart $msg body $part $enc]} res] {
      $tw insert insert "\n\nMIME-ERROR: $res\n\n"
    }
  } elseif {$fulltype == "text/enriched" || $fulltype == "text/richtext"} {
    set charset [$fid message mimepart $msg param $part charset]
    if ![string length $charset] { set charset us-ascii }
    mfv:parse-enriched $tw $fid $msg $part $charset {} [expr {$subtype == "richtext"}]
  } elseif {$type == "message"} {
    $tw insert insert "\nSORRY.  $type/$subtype not handled yet\n\n"
  } else {
    if {$type == "image"} {
      if ![catch {$fid message mimepart $msg write $part {} $enc} res] {
	set tmpfile $res
	switch -regexp -- $subtype {
	  {^(xbm|x-xbm|bitmap)$} {set fmt bitmap}
	  {^(xpm|x-xpm|pixmap)$} {set fmt pixmap}
	  default {set fmt photo}
	}
	if ![catch {image create $fmt image$part -file $tmpfile} res] {
	  set frame $top.mimelbl[join [split $part .] _]
	  if [winfo exists $frame] { destroy $frame }
	  label $frame -image image$part
	  $tw insert insert \n
	  $tw window create insert -window $frame
	  $tw insert insert \n
	  return
	}
      }
    }
    $tw insert insert "\nATTACHMENT: $type/$subtype  "
    set btn $top.mimebtn[join [split $part .] _]
    if ![winfo exists $btn] { button $btn -text View }
    $btn configure -command "mfv:mime-external-view $tw $fid $msg $part 0"
    bind $btn <ButtonRelease-3> "mfv:mime-external-view $tw $fid $msg $part 1"
    $tw window create insert -window $btn
    set desc [$fid message mimepart $msg description $part]
    if {[string length $desc]} {
      $tw insert insert "\n\t$desc\n"
    } else {
      $tw insert insert "\n"
    }
  }
}

proc mfv:mime-external-view { tw fid msg part {prompt 0}} {
  global mf mfp mfdb

  set top [winfo toplevel $tw]
  mfv:wait-on

  set type [$fid message mimepart $msg type $part]
  set subtype [$fid message mimepart $msg subtype $part]
  set ftype "$type/$subtype"

  # TODO: parse /etc/mailcap?
  set cmd $mf(mime-external-default)
  foreach rule $mf(mime-external-viewers) {
    if {[regexp -nocase "^${ftype}$" [lindex $rule 0]]} {
      set cmd [lindex $rule 1]
      break
    }
    if {[regexp -nocase "^${type}$" [lindex $rule 0]]} {
      set cmd [lindex $rule 1]
    }
  }

  # default to prompting user for file to write contents to
  if {![string length [string trim $cmd]] || 
      [regexp -nocase "@prompt" $cmd] || $prompt} {
    set res [mfv:mime-to-file $tw $fid $msg $part]
    mfv:wait-off
    return $res
  }

  set enc [$fid message mimepart $msg encoding $part]
  if [catch {$fid message mimepart $msg write $part {} $enc} file] {
    mfv:error-mesg $file
    mfv:wait-off; return 1
  }

  # run desired command in background
  set cmd "exec $cmd"
  if {[regsub -all {([^%]|^)%([FTtAS])} $cmd "\\1\004\\2\004" cmd]} {
    regsub -all {%%} $cmd {%} cmd
    if {![regsub -all "\004F\004" $cmd $file cmd]} {
      append cmd " $file" 
    }
    #TODO: regsub -all "\004T\004" $cmd "{$ftype; $param}" cmd
    regsub -all "\004t\004" $cmd $ftype cmd
    set whofrom [$fid message field $msg from]
    regsub -all "\004A\004" $cmd "{$whofrom}" cmd
    set subject [$fid message field $msg subject]
    regsub -all "\004S\004" $cmd "{$subject}" cmd

  } else {
    regsub -all {%%} $cmd {%} cmd
    append cmd " $file" 
  }

  set cmd [string trim $cmd]
  if {[string index $cmd [expr [string length $cmd]-1]] != "&"} {append cmd " &"}
  # puts stderr $cmd
  if ![catch $cmd res] {
    mfv:log-mesg $top "Ran $cmd in background"
  } else {
    mfv:error-mesg $res
    mfv:wait-off; return 1
  }
  mfv:wait-off; return 0
}

proc mfv:mime-to-file { tw fid msg part } {
  set top [winfo toplevel $tw]

  set default [$fid message mimepart $msg param $part name]
  set dispos [$fid message mimepart $msg disposition $part]
  if [regexp -nocase {filename=\"*([^;\"]+)} $dispos trash name] {
    set default $name
  } elseif [string length $dispos] {
    puts stderr "Strange Dispos: $dispos"
  }

  set encfile [ut:getstr -prompt "Enter filename to save attachment in:" \
		  -master $top -fc 1 -default $default]
  if {![string length $encfile]} {
    return 0
  }
  set putdir [file dirname $encfile]
  set encfile [file tail $encfile]
  if {![file isdirectory $putdir]} {
    mfv:error-mesg "$putdir is not a directory" $top
    return 255
  }
  if {[file exists $putdir/$encfile]} {
    if {![ut:getok -master $top -prompt "Overwrite existing file $encfile?"]} {
      return 0
    }
  }

  set enc [$fid message mimepart $msg encoding $part]
  if [catch {$fid message mimepart $msg write $part $putdir/$encfile $enc} res] {
    mfv:error-mesg $res
    return 1
  }

  mfv:log-mesg $top "Message $msg/$part contents written to $putdir/$encfile"
  return 0
}

proc mfv:get-font {tw base weight slant size charset} {

  set charset [string tolower $charset]
  if {$charset == "us-ascii"} { 
    set charset *
  } elseif {[regexp {iso-8859-([1-9])} $charset trash num]} {
    set charset "iso8859-$num"
  }

  set font "-$base-$weight-$slant-normal-*-$size-*-*-*-*-*-$charset"
  if {![catch "$tw tag configure test -font \$font" res]} {
    return $font
  }

  if {$weight == "medium"} {
    set font "-$base-regular-$slant-normal-*-$size-*-*-*-*-*-$charset"
    if {![catch "$tw tag configure test -font \$font"]} {
      return $font
    }
  }

  if {$slant == "i"} {
    set font "-$base-$weight-o-normal-*-$size-*-*-*-*-*-$charset"
    if {![catch "$tw tag configure test -font \$font"]} {
      return $font
    }
    if {$weight == "medium"} {
      set font "-$base-regular-o-normal-*-$size-*-*-*-*-*-$charset"
      if {![catch "$tw tag configure test -font \$font"]} {
	return $font
      }
    }
  }

  if {$charset != "*"} {
    return [mfv:get-font $tw $base $weight $slant $size *]
  }
  return fixed
}

proc mfv:set-tag-font {tw font under justify} {
  if {[lsearch [$tw tag names] t$under-$font-$justify] > -1} return
  $tw tag configure t$under-$font-$justify -font $font -underline $under -justify $justify
}

proc mfv:parse-enriched {tw fid msg part charset prefix {richtext 0}} {
  global mf mfp mfdb

  set tagslist {}
  set tagstart [$tw index insert]
  set weight medium
  set slant r
  set fntbase "[lindex $mf(mime-font-default) 0]-[lindex $mf(mime-font-default) 1]"
  set fntsize [lindex $mf(mime-font-default) 2]
  set curfont [mfv:get-font $tw $fntbase medium r $fntsize $charset]
  set curtag t0-$curfont-left
  mfv:set-tag-font $tw $curfont 0 left

  set chars 0
  set on 1
  set charsetlist $charset

  set nofill 0
  set just {0 0 0}
  set justify left
  set bold 0
  set italic 0
  set fixed 0
  set smaller 0
  set bigger 0
  set underline 0
  set excerpt 0
  set param 0

  set indent 0
  set indenttxt $prefix
  set indentlen [string length $indenttxt]
  set indentright 0
  set max 72

  set enc [$fid message mimepart $msg encoding $part]

  set bodylist [split [$fid message mimepart $msg body $part $enc] \n]
  set lastline [llength $bodylist]

  for {set lineno 0} {$lineno < $lastline} {incr lineno} {
    set line [lindex $bodylist $lineno]
    if {$on && (([lempty $line] && !$richtext) || $nofill)} {
      $tw insert insert \n
      set chars 0
      continue
    }
    append line " "
    while {[set ndx [string first "<" $line]] > -1} {
      set skipit 0
      set str [string range $line 0 [expr $ndx-1]]
      set line [string range $line [incr ndx] end]
      if {[string first "<" $line] == 0} {
	append str "<"
	set line [string range $line 1 end]
	set skipit 1
      }
      if {[set len [string length $str]] && $on} {
	if {!$chars} {
	  $tw insert insert $indenttxt
	  set chars $indentlen
	}
	set lastchar [expr $max-$chars]
	while {$len > $lastchar} {
	  while {![string match {[ 	]} [string index $str $lastchar]] &&
		 $lastchar > 0} {
	    incr lastchar -1
	  }
	  if {$lastchar < 1} {
	    set lastchar [expr $max-$chars]
	    while {![string match {[ 	]} [string index $str $lastchar]] &&
		   $lastchar < $len} {
	      incr lastchar
	    }
	  }
	  $tw insert insert [string range $str 0 $lastchar]
	  incr lastchar
	  set str [string trimleft [string range $str $lastchar end]]
	  set len [string length $str]
	  $tw insert insert "\n$indenttxt"
	  set chars $indentlen
	  set lastchar [expr $max-$chars]
	}
	$tw insert insert $str
	incr chars $len
      }
      if {$skipit} continue
      while {[set ndx [string first ">" $line]] < 0} {
	incr lineno
	if {$lineno >= $lastline} { 
	  mfv:error-msg "Error parsing enriched text" [winfo toplevel $tw]
	  return
	}
	append line [lindex $bodytext $lineno]
      }
      set format [string trim [string tolower [string range $line 0 [expr $ndx-1]]]]
      set line [string range $line [incr ndx] end]
      if {!$chars} {
	set line [string trimleft $line]
      }
      set update 0
      switch -regexp $format {
	{^lt} {
	  $tw insert insert {<}
	}
	{^nl} {
	  $tw insert insert \n
	  set chars 0
	}
	{^np} {
	  $tw insert insert \n\n\n
	  set chars 0
	}
	{/paragraph} {
	  $tw insert insert \n\n
	  set chars 0
	}
	{paragraph} {
	  if [$tw compare "insert linestart" != insert] {
	    $tw insert insert \n\n
	  } elseif [$tw compare "insert -1 line linestart" != "insert -1 line end"] {
	    $tw insert insert \n
	  }
	  set chars 0
	}
	{(/us-ascii|/iso-8859-.*)} {
	  set charsetlist [lreplace $charsetlist 0 0]
	  if [llength $charsetlist] {
	    set charset [lindex $charsetlist 0]
	    set update 1
	  } else {
	    set charsetlist $charset
	  }
	}
	{(us-ascii|iso-8859-.*)} {
	  set charsetlist [linsert $charsetlist 0 $format]
	  set charset us-ascii
	  set update 1
	}
	{/bold} {
	  incr bold -1
	  if {!$bold} {set weight medium; set update 1}
	}
	{bold} {
	  if {!$bold} {set weight bold; set update 1}
	  incr bold
	}
	{/italic} {
	  incr italic -1
	  if {!$italic} {set slant r; set update 1}
	}
	{italic} {
	  if {!$italic} {set slant i; set update 1}
	  incr italic
	}
	{/underline} {
	  incr underline -1
	  if {!$underline} {set update 1}
	}
	{underline} {
	  if {!$underline} {set update 1}
	  incr underline
	}
	{/fixed} {
	  incr fixed -1
	  if {!$fixed} {
	    set fntbase "[lindex $mf(mime-font-default) 0]-[lindex $mf(mime-font-default) 1]"
	    set update 1
	  }
	}
	{fixed} {
	  if {!$fixed} {
	    set fntbase "[lindex $mf(mime-font-fixed) 0]-[lindex $mf(mime-font-fixed) 1]"
	    set update 1
	  }
	  incr fixed
	}
	{/smaller} {
	  incr fntsize 2
	  set update 1
	  incr smaller -1
	}
	{smaller} {
	  incr fntsize -2
	  set update 1
	  incr smaller
	}
	{/bigger} {
	  incr fntsize -2
	  set update 1
	  incr smaller -1
	}
	{bigger} {
	  incr fntsize 2
	  set update 1
	  incr smaller
	}
	{/nofill} {
	  set just [lreplace $just 0 0]
	  set nofill [lindex $just 0]
	  if {$on} {
	    $tw insert insert \n
	    set chars 0
	  }
	}
	{nofill} {
	  set just [linsert $just 0 1]
	  set nofill 1
	  if {$on} {
	    $tw insert insert \n
	    set chars 0
	  }
	}
	{/center} {
	  set just [lreplace $just 0 0]
	  set nofill [lindex $just 0]
	  set justify [lreplace $justify 0 0]
	  set update 1
	  if {$on} {
	    $tw insert insert \n
	    set chars 0
	  }
	}
	{center} {
	  set just [linsert $just 0 0]
	  set nofill 0
	  set justify [linsert $justify 0 center]
	  set update 1
	  if {$on} {
	    $tw insert insert \n
	    set chars 0
	  }
	}
	{/flush.*} {
	  set just [lreplace $just 0 0]
	  set nofill [lindex $just 0]
	  set justify [lreplace $justify 0 0]
	  set update 1
	  if {$on} {
	    $tw insert insert \n
	    set chars 0
	  }
	}
	{flush.*} {
	  set just [linsert $just 0 0]
	  set nofill 0
	  set justify [linsert $justify 0 [string range $format 5 end]]
	  set update 1
	  if {$on} {
	    $tw insert insert \n
	    set chars 0
	  }
	}
	{(/indentright|^outdentright)} {
	  incr indentright -1
	  incr max 4
	}
	{(indentright|/outdentright)} {
	  incr indentright
	  incr max -4
	}
	{(/indent|^outdent)} {
	  incr indent -1
	  if {$indent < 0} {
	    set indent 0
	  } else {
	    set indenttxt [string range $indenttxt 0 [expr $indentlen-5]]
	    set indentlen [string length $indenttxt]
	  }
	}
	{(indent|/outdent)} {
	  incr indent
	  append indenttxt "    "
	  set indentlen [string length $indenttxt]
	  if {!$chars && $on} {
	    $tw insert insert $indenttxt
	    set chars $indentlen
	  }
	}
	{(/excerpt|/signature)} {
	  incr indent -1
	  set indenttxt [string range $indenttxt 0 [expr $indentlen-5]]
	  set indentlen [string length $indenttxt]
	  incr indentright -1
	  incr max 4
	}
	{(excerpt|signature)} {
	  incr indent
	  append indenttxt "    "
	  set indentlen [string length $indenttxt]
	  incr indentright
	  incr max -4
	}
	{(/comment|/param|/heading|/footing)} {
	  set on 1
	}
	{(comment|param|heading|footing)} {
	  set on 0
	}
      }
      if {$update} {
	lappend tagslist [list $curtag $tagstart [$tw index insert]]
	set tagstart [$tw index insert]
	set curfont [mfv:get-font $tw $fntbase $weight $slant $fntsize $charset]
	mfv:set-tag-font $tw $curfont $underline [lindex $justify 0]
	set curtag t$underline-$curfont-[lindex $justify 0]
      }
    }
    if {[set len [string length $line]] && $on} {
      if {!$chars} {
	$tw insert insert $indenttxt
	set chars $indentlen
      }
      set lastchar [expr $max-$chars]
      while {$len > $lastchar} {
	while {![string match {[ 	]} [string index $line $lastchar]] &&
	       $lastchar > 0} {
	  incr lastchar -1
	}
	if {$lastchar < 1} {
	  set lastchar [expr $max-$chars]
	  while {![string match {[ 	]} [string index $line $lastchar]] &&
		 $lastchar < $len} {
	    incr lastchar
	  }
	}
	$tw insert insert "[string range $line 0 $lastchar]\n$indenttxt"
	incr lastchar
	set line [string trimleft [string range $line $lastchar end]]
	set len [string length $line]
	set chars $indentlen
	set lastchar [expr $max-$chars]
      }
      $tw insert insert $line
      incr chars $len
    }

  }

  lappend tagslist [list $curtag $tagstart [$tw index insert]]
  foreach tagspec $tagslist {
    $tw tag add [lindex $tagspec 0] [lindex $tagspec 1] [lindex $tagspec 2] 
  }
}

proc mfv:mime-attach { mfc type subtype {params {}} {enc {}} {file {}} {desc {}}} {
  global mf mfp

  tkTextUndoSetup $mfc.comp.txt

  if {!$mfp($mfc,mime)} {
    set mfp($mfc,bound) [mfv_util boundary]
    set bound "$mfp($mfc,bound)-0"
    $mfc.comp.txt insert 1.0 "Content-Transfer-Encoding: 7bit\n"
    $mfc.comp.txt insert 1.0 "Content-Type: multipart/mixed; boundary=\"$bound\"\n"
    $mfc.comp.txt insert 1.0 "Mime-Version: 1.0\n"

    $mfc.comp.txt mark set insert "headerend +1 line linestart"
    $mfc.comp.txt insert insert "This is  a multimedia message in MIME  format.  If you are reading this\n"
    $mfc.comp.txt insert insert "prefix, your mail reader does  not understand MIME or is not currently\n"
    $mfc.comp.txt insert insert "configured to parse MIME messages.  You may wish to look into\n"
    $mfc.comp.txt insert insert "upgrading to a mail reader that does.\n\n"
    $mfc.comp.txt insert insert "--$bound\n"
    $mfc.comp.txt insert insert "Content-Type: text/plain; charset=us-ascii\n\n"
    
    $mfc.comp.txt mark set insert end
    $mfc.comp.txt insert insert "\n--$bound--\n"
    $mfc.comp.txt mark set multiend "end -4c"
    $mfc.comp.txt insert insert "\nDO NOT DELETE the above boundary line."
    $mfc.comp.txt insert insert "\nAnything placed after this line will be ignored by MIME readers.\n"
    set mfp($mfc,mime) 1

  } else {
    set bound "$mfp($mfc,bound)-0"
  }
  $mfc.comp.txt mark set insert "multiend linestart"
  $mfc.comp.txt insert insert "--$bound\n"
  $mfc.comp.txt insert insert "Content-Type: $type/$subtype"
  if {[string length $params]} {
    foreach param $params {
      set start [$mfc.comp.txt index insert]
      $mfc.comp.txt insert insert "; $param"
      if {[lindex [split [$mfc.comp.txt index insert] .] 1] > 72} {
	$mfc.comp.txt insert "$start +1 char" "\n\t"
      }
    }
  } else { 
    $mfc.comp.txt insert insert "\n"
  }
  if {[string length $enc]} {
    $mfc.comp.txt insert insert "Content-Transfer-Encoding: $enc\n"
  }
  if {[string length $desc]} {
    $mfc.comp.txt insert insert "Content-Description: $desc\n"
  }
  $mfc.comp.txt insert insert "\n\n\n\n"
  $mfc.comp.txt mark set insert "insert -2 char"

  if {[string length $file]} {
    $mfc.comp.txt insert insert "  ATTACHED FILE ($enc): $file  \n"
    $mfc.comp.txt tag configure attachedfile -borderwidth 2 -relief raised \
      -background [lindex [$mfc.bb.cancel configure -background] 4] \
      -font [lindex [$mfc.bb.cancel configure -font] 4]
    $mfc.comp.txt mark set insert "insert -1 line"
    $mfc.comp.txt tag add attachedfile insert "insert lineend"
    $mfc.comp.txt mark set insert "insert +1 line"
  }
  $mfc.comp.txt yview -pickplace insert
}

proc mfv:mime-attach-select {mfc} {
  global mf mfp


  set w .mime_attach
  toplevel $w -class MailMime
  wm minsize $w 400 260
  wm protocol $w WM_DELETE_WINDOW "$w.bb.cancel invoke"
  set xpos [expr [winfo rootx $mfc]+[winfo width $mfc]/3]
  set ypos [expr [winfo rooty $mfc]+[winfo height $mfc]/3]
  wm geometry $w +${xpos}+${ypos}

  wm title $w "Mime Attachment for $mfc"

  frame $w.type -borderwidth 5
  ut:combo-create -frame $w.type -default text -editable 1 \
      -deflist {text message application image audio video} \
      -command {mfv:mime-type-select %W %E} -label "Type:" \
      -labelwidth 12

  frame $w.subtype -borderwidth 5
  ut:combo-create -frame $w.subtype -default plain -editable 1 \
      -deflist {plain enriched} -label "Subtype:" \
      -labelwidth 12

  frame $w.enc -borderwidth 5
  ut:combo-create -frame $w.enc -default 7bit -editable 1 \
      -deflist {7bit quoted-printable base64} -label "Encoding:" \
      -labelwidth 12

  frame $w.param -borderwidth 5
  label $w.param.lbl -text "Parameters:" -width 12 -anchor e
  entry $w.param.ent -relief sunken
  pack $w.param.lbl -side left
  pack $w.param.ent -side left -fill x -expand true -ipady 2

  frame $w.desc -borderwidth 5
  label $w.desc.lbl -text "Description:" -width 12 -anchor e
  entry $w.desc.ent -relief sunken
  pack $w.desc.lbl -side left
  pack $w.desc.ent -side left -fill x -expand true -ipady 2

  frame $w.file -borderwidth 5
  label $w.file.lbl -text "File:" -width 12 -anchor e
  entry $w.file.ent -relief sunken
  button $w.file.btn -text ">>" -width 2 \
	  -command "set val \[$w.file.ent get\]
		    $w.file.ent delete 0 end
		    $w.file.ent insert 0 \[mfv:get-filename -master $w -cancelvalue \$val \]"
  pack $w.file.lbl -side left
  pack $w.file.ent -side left -fill x -expand true -ipady 2
  pack $w.file.btn -side left -padx 5

  frame $w.bb -borderwidth 5
  button $w.bb.ok -text "Attach" -width 8 \
      -command "mfv:mime-attach-done $w $mfc; grab release $w; destroy $w"
  button $w.bb.cancel -text Cancel -width 8 \
      -command "grab release $w; destroy $w"
  pack $w.bb.ok $w.bb.cancel -side left -padx 10 -pady 5

  pack $w.type $w.subtype $w.enc $w.param $w.desc \
      $w.file -side top -fill x -expand true -padx 10
  frame $w.sep -bd 2 -height 4 -relief sunken
  pack $w.sep -side top -fill x -expand true -pady 5
  pack $w.bb -side top

  bind $w.file.ent <Key-Tab> {
    set f [%W get]
    %W delete 0 end
    %W insert end [j:expand_filename $f]
  }

  after 20 grab $w
  set savefocus [focus]
  focus $w.type.ent
  tkwait window $w
  grab release $w
  focus $savefocus
}

# {text message application image audio video}
proc mfv:mime-type-select { w type } {

  set def {}
  set deflist {}
  set enc 7bit

  set type [string tolower $type]
  switch -exact $type {

    {text} {
      set def plain
      set deflist {plain enriched}
      set enc 7bit
    }
    {message} {
      set def external-body
      set deflist {external-body rfc822}
      set enc 7bit
    }
    {application} {
      set def octet-stream
      set deflist {octet-stream postscript}
      set enc base64
    }
    {image} {
      set def gif
      set deflist {gif jpeg}
      set enc base64
    }
    {audio} {
      set def basic
      set deflist basic
      set enc base64
    }
    {video} {
      set def mpeg
      set deflist mpeg
      set enc base64
    }
  }

  ut:combo-reset [string trimright $w type]subtype $def $deflist 0
  ut:combo-reset [string trimright $w type]enc $enc {7bit quoted-printable base64} 0

}

proc mfv:mime-attach-done { w mfc } {

  set type [ut:combo-get $w.type]
  set subtype [ut:combo-get $w.subtype]
  set enc [ut:combo-get $w.enc]

  set params [$w.param.ent get]
  set desc [$w.desc.ent get]
  set file [j:expand_filename [$w.file.ent get]]

  mfv:mime-attach $mfc $type $subtype $params $enc $file $desc
}