+ incr lno
+ errexpect-setline $lno $l
+ set l [string trim $l]
+ if {![string length $l]} continue
+ if {[regexp {^\#} $l]} continue
+ if {![regexp -expanded \
+ {^ (\d+) (?: \s+([^=]*?) )? \s* =
+ (?: \s* (\S+)
+ (?: \s+ (\S+) )?)? $} \
+ $l dummy vid vname owner note]} {
+ errexpect-error "badly formatted"
+ }
+ set vname [string trim $vname]
+ if {[info exists notes($vid)]} {
+ errexpect-error "duplicate vesselid $vid"
+ }
+ set notes($vid) [list $lno $vname $owner $note]
+ }
+}
+
+proc note-info {lno vid name island description} {
+ global note_infos
+ lappend note_infos [list $lno $vid $name $island $description]
+}
+
+proc display-note-infos {} {
+ global note_infos note_missings notes
+
+ set nmissing [llength $note_missings]
+ debug "display-note-infos $nmissing [array size notes]"
+
+ if {[llength $note_infos]} {
+ set tiny "[llength $note_infos] warning(s)"
+ } elseif {$nmissing && [array size notes]} {
+ set tiny "$nmissing missing"
+ } else {
+ return
+ }
+
+ set infodata {}
+
+ foreach info $note_infos {
+ manyset $info lno vid name island description
+ append infodata "vessel"
+ append infodata " $vid"
+ if {[string length $name]} { append infodata " $name" }
+ if {[string length $island]} { append infodata " ($island)" }
+ append infodata ": " $description "\n"
+ }
+
+ if {$nmissing} {
+ if {[string length $infodata]} { append infodata "\n" }
+ append infodata "$nmissing vessel(s) not mentioned in notes:\n"
+ set last_island {}
+ foreach info [lsort $note_missings] {
+ manyset $info island name vid
+ if {[string compare $island $last_island]} {
+ append infodata "# $island:\n"
+ set last_island $island
+ }
+ append infodata [format "%-9d %-29s =\n" $vid $name]
+ }
+ }
+
+ parser-control-failed-core .cp.ctrl.notes notes \
+ white blue 0 \
+ $tiny \
+ "[llength $note_infos] warning(s);\
+ $nmissing vessel(s) missing" \
+ "Full description of warnings and missing vessels:" \
+ $infodata
+}
+
+#---------- vessel properties ----------
+
+proc vesselclasses-init {} {
+ global vc_game2code vc_code2abbrev vc_code2full vc_codes
+ set vcl {
+ smsloop am sl Sloop
+ lgsloop bm ct Cutter
+ dhow cm dh Dhow
+ longship dm ls Longship
+ baghlah em bg Baghlah
+ merchbrig fm mb {Merchant Brig}
+ warbrig gm wb {War Brig}
+ xebec hm xe Xebec
+ merchgal jm mg {Merchant Galleon}
+ warfrig im wf {War Frigate}
+ grandfrig km gf {Grand Frigate}
+ }
+ set vc_codes {}
+ foreach {game code abbrev full} $vcl {
+ lappend vc_codes $code
+ set vc_game2code($game) $code
+ set vc_code2abbrev($code) $abbrev
+ set vc_code2full($code) $full
+ load-icon $abbrev
+ }
+
+ load-icon unlocked
+ load-icon locked
+ load-icon battle
+ load-icon atsea
+ load-icon borrow
+ load-icon query
+ load-icon ours
+ load-icon dot
+}
+
+proc load-icon {icon} {
+ image create bitmap icon/$icon -file icons/$icon.xbm
+}
+
+proc code2abbrev-lock {lockown} {
+ manyset [split $lockown ""] lock notown
+ append abbrev [lindex {x u .} $lock]
+ append abbrev [lindex {m . ?} [regsub {\D} $notown 2]]
+}
+
+proc canvas-horiz-stack {xvar xoff y bind type args} {
+ upvar 1 $xvar x
+ upvar 1 canvas canvas
+ set id [eval $canvas create $type [expr {$x+$xoff}] $y $args]
+ set bbox [$canvas bbox $id]
+ set x [lindex $bbox 2]
+ $canvas bind $id <ButtonPress> $bind
+ return $id
+}
+
+proc code2canvas {code canvas x yvar qty qtylen bind} {
+ global vc_code2abbrev
+ upvar 1 $yvar y
+
+ manyset [split $code _] inport class subclass lockown xabbrev
+
+ set stackx $x
+ incr stackx 2
+ set imy [expr {$y+2}]
+
+ if {!$inport} { incr qtylen -1 }
+ if {$qtylen<=0} { set qtylen {} }
+ set qty [format "%${qtylen}s" $qty]
+
+ set qtyid [canvas-horiz-stack stackx 0 $y $bind \
+ text -anchor nw -font fixed -text $qty]
+
+ if {!$inport} {
+ canvas-horiz-stack stackx 0 $imy $bind \
+ image -anchor nw -image icon/atsea
+ incr stackx
+ }
+
+ canvas-horiz-stack stackx -1 $imy $bind \
+ image -anchor nw -image icon/$vc_code2abbrev($class)
+
+ if {[string length $subclass]} {
+ canvas-horiz-stack stackx 0 $y $bind \
+ text -anchor nw -font fixed -text \
+ $subclass
+ }
+
+ manyset [split $lockown ""] lock notown
+
+ incr stackx
+ canvas-horiz-stack stackx 0 $imy $bind \
+ image -anchor nw -image icon/[lindex {battle borrow dot} $lock]
+ incr stackx
+ canvas-horiz-stack stackx 0 $imy $bind \
+ image -anchor nw -image icon/[lindex {ours dot query} \
+ [regsub {\D} $notown 2]]
+ incr stackx
+
+ if {[string length $xabbrev]} {
+ canvas-horiz-stack stackx 0 $y $bind \
+ text -anchor nw -font fixed -text \
+ $xabbrev
+ }
+
+ set bbox [$canvas bbox $qtyid]
+ set ny [lindex $bbox 3]
+ set bid [$canvas create rectangle \
+ $x $y $stackx $ny \
+ -fill white]
+
+ set y $ny
+ $canvas lower $bid $qtyid
+
+ $canvas bind $bid <ButtonPress> $bind
+}
+
+proc show-report-decode {code} {
+ global vc_code2full
+
+ manyset [split $code _] inport classcode subclass lockown xabbrev
+ manyset [split $lockown ""] lock notown
+
+ report-set inport [lindex {{At Sea} {In port}} $inport]
+ report-set class $vc_code2full($classcode)
+
+ switch -exact $subclass {
+ {} { report-set subclass {Ordinary} }
+ F { report-set subclass {"Frost class"} }
+ default { report-set subclass "Subclass \"$subclass\"" }
+ }
+
+ report-set lock [lindex {
+ {Battle ready} {Unlocked} {Locked}
+ } $lock]
+
+ switch -exact $notown {
+ 0 { report-set own "Yours" }
+ 1 { report-set own "Other pirate's" }
+ U { report-set own "Owner not known" }
+ M { report-set own "Missing from notes" }
+ default { report-set own "?? $notown" }
+ }
+
+ if {[string length $xabbrev]} {
+ report-set xabbrev "Notes flags: $xabbrev"
+ } else {
+ report-set xabbrev "No flags in notes"
+ }
+}
+
+#---------- filtering ----------
+
+set filters {}
+
+proc filter-values/size {} { global vc_codes; return $vc_codes }
+proc filter-icon/size {code} {
+ upvar #0 vc_code2abbrev($code) abb
+ return icon/$abb
+}
+proc filter-default/size {code} { return 1 }
+proc filter-says-yes/size {codel} {
+ set sizecode [lindex $codel 1]
+ upvar #0 filter_size($sizecode) yes
+ return $yes
+}
+
+proc filter-values/lockown {} {
+ foreach lv {0 1 2} {
+ foreach ov {0 1 X} {
+ lappend vals "$lv$ov"
+ }