Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
header.tcl
Go to the documentation of this file.
1 ###
2 ### search/header.tcl: Header Search routines for Scid.
3 ###
4 
5 namespace eval ::search::header {}
6 
7 set sTitleList [list gm im fm none wgm wim wfm w]
8 foreach i $sTitleList {
9  set sTitles(w:$i) 1
10  set sTitles(b:$i) 1
11 }
12 set sHeaderFlagList {StdStart Promotions Comments Variations Annotations \
13  DeleteFlag WhiteOpFlag BlackOpFlag MiddlegameFlag EndgameFlag \
14  NoveltyFlag PawnFlag TacticsFlag KsideFlag QsideFlag \
15  BrilliancyFlag BlunderFlag UserFlag }
16 
17 set sHeaderCustomFlagList { CustomFlag1 CustomFlag2 CustomFlag3 CustomFlag4 CustomFlag5 CustomFlag6 }
18 
19 set sHeaderFlagChars {S X _ _ _ D W B M E N P T K Q ! ? U 1 2 3 4 5 6}
20 
21 set sPgntext(1) ""
22 set sPgntext(2) ""
23 set sPgntext(3) ""
24 
25 # checkDates:
26 # Checks minimum/maximum search dates in header search window and
27 # extends them if necessary.
28 proc checkDates {} {
29  global sDateMin sDateMax sEventDateMin sEventDateMax
30  if {[string length $sDateMin] == 4} { append sDateMin ".??.??"}
31  if {[string length $sDateMax] == 4} { append sDateMax ".12.31"}
32  if {[string length $sDateMin] == 7} { append sDateMin ".??"}
33  if {[string length $sDateMax] == 7} { append sDateMax ".31"}
34  if {[string length $sEventDateMin] == 4} { append sDateMin ".??.??"}
35  if {[string length $sEventDateMax] == 4} { append sDateMax ".12.31"}
36  if {[string length $sEventDateMin] == 7} { append sDateMin ".??"}
37  if {[string length $sEventDateMax] == 7} { append sDateMax ".31"}
38 }
39 
40 proc ::search::header::defaults {} {
41  set ::sWhite ""; set ::sBlack ""
42  set ::sEvent ""; set ::sSite ""; set ::sRound ""; set ::sAnnotator ""; set ::sAnnotated 0
43  set ::sWhiteEloMin ""; set ::sWhiteEloMax ""
44  set ::sBlackEloMin ""; set ::sBlackEloMax ""
45  set ::sEloDiffMin ""; set ::sEloDiffMax ""
46  set ::sGlMin ""; set ::sGlMax ""
47  set ::sEcoMin ""; set ::sEcoMax ""; set ::sEco Yes
48  set ::sGnumMin ""; set ::sGnumMax ""
49  set ::sDateMin ""; set ::sDateMax ""
50  set ::sEventDateMin ""; set ::sEventDateMax ""
51  set ::sResWin ""; set ::sResLoss ""; set ::sResDraw ""; set ::sResOther ""
52  set ::sIgnoreCol No
53  set ::sSideToMoveW "w"
54  set ::sSideToMoveB "b"
55  foreach flag [ concat $::sHeaderFlagList $::sHeaderCustomFlagList] { set ::sHeaderFlags($flag) both}
56  foreach i [array names ::sPgntext] { set ::sPgntext($i) ""}
57  foreach i $::sTitleList {
58  set ::sTitles(w:$i) 1
59  set ::sTitles(b:$i) 1
60  }
61 }
62 
63 foreach i {sWhiteEloMin sWhiteEloMax sBlackEloMin sBlackEloMax} {
64  trace variable $i w [list ::utils::validate::Integer [sc_info limit elo] 0]
65 }
66 trace variable sEloDiffMin w [list ::utils::validate::Integer "-[sc_info limit elo]" 0]
67 trace variable sEloDiffMax w [list ::utils::validate::Integer "-[sc_info limit elo]" 0]
68 
70 
71 trace variable sDateMin w ::utils::validate::Date
72 trace variable sDateMax w ::utils::validate::Date
73 trace variable sEventDateMin w ::utils::validate::Date
74 trace variable sEventDateMax w ::utils::validate::Date
75 
76 
77 trace variable sGlMin w {::utils::validate::Integer 9999 0}
78 trace variable sGlMax w {::utils::validate::Integer 9999 0}
79 
80 trace variable sGnumMin w {::utils::validate::Integer -9999999 0}
81 trace variable sGnumMax w {::utils::validate::Integer -9999999 0}
82 
83 # Forcing ECO entry to be valid ECO codes:
84 foreach i {sEcoMin sEcoMax} {
85  trace variable $i w {::utils::validate::Regexp {^$|^[A-Ea-e]$|^[A-Ea-e][0-9]$|^[A-Ea-e][0-9][0-9]$|^[A-Ea-e][0-9][0-9][a-z]$|^[A-Ea-e][0-9][0-9][a-z][1-4]$}}
86 }
87 
88 set sHeaderFlagFrame 0
89 
90 # ::search::header
91 #
92 # Opens the window for searching by header information.
93 #
94 proc ::search::header {{ref_base ""} {ref_filter "dbfilter"}} {
95  ::search::Open $ref_base $ref_filter HeaderSearch ::search::headerCreateFrame
96 }
97 
98 proc search::headerCreateFrame { w } {
99  global sWhite sBlack sEvent sSite sRound sAnnotator sAnnotated sEventDateMin sEventDateMax sIgnoreCol
100  global sWhiteEloMin sWhiteEloMax sBlackEloMin sBlackEloMax
101  global sEloDiffMin sEloDiffMax sSideToMoveW sSideToMoveB
102  global sEco sEcoMin sEcoMax sHeaderFlags sGlMin sGlMax sTitleList sTitles
103  global sResWin sResLoss sResDraw sResOther sPgntext
104 
105  foreach frame {cWhite cBlack ignore tw tb eventsite eventround date res ano gl ends eco} {
106  ttk::frame $w.$frame
107  }
108 
109  set regular font_Small
110  ttk::labelframe $w.player -text $::tr(Player)
111  pack $w.player -side top -fill x -pady 5
112  foreach color {White Black} {
113  pack $w.c$color -side top -fill x -in $w.player
114  ttk::label $w.c$color.lab -textvar ::tr($color:) -width 9 -anchor w
115  ttk::combobox $w.c$color.e -textvariable "s$color" -width 40
116  ::utils::history::SetCombobox HeaderSearch$color $w.c$color.e
117 
118  ttk::label $w.c$color.space
119  ttk::label $w.c$color.elo1 -textvar ::tr(Rating:)
120  ttk::entry $w.c$color.elomin -textvar s${color}EloMin -width 6 -justify right
121  ttk::label $w.c$color.elo2 -text "-"
122  ttk::entry $w.c$color.elomax -textvar s${color}EloMax -width 6 -justify right
123  bindFocusColors $w.c$color.e
124  bindFocusColors $w.c$color.elomin
125  bindFocusColors $w.c$color.elomax
126  pack $w.c$color.lab $w.c$color.e $w.c$color.space -side left
127  pack $w.c$color.elomax $w.c$color.elo2 $w.c$color.elomin $w.c$color.elo1 -side right
128  }
129 
130  pack $w.ignore -side top -fill x -in $w.player
131  ttk::checkbutton $w.ignore.yes -variable sIgnoreCol -onvalue Yes -offvalue No -textvar ::tr(IgnoreColors)
132  pack $w.ignore.yes -side left
133  ttk::label $w.ignore.rdiff -textvar ::tr(RatingDiff:)
134  ttk::entry $w.ignore.rdmin -width 6 -textvar sEloDiffMin -justify right
135  ttk::label $w.ignore.rdto -text "-"
136  ttk::entry $w.ignore.rdmax -width 6 -textvar sEloDiffMax -justify right
137  bindFocusColors $w.ignore.rdmin
138  bindFocusColors $w.ignore.rdmax
139  pack $w.ignore.rdmax $w.ignore.rdto $w.ignore.rdmin $w.ignore.rdiff -side right
140 
141  pack [ttk::separator $w.sep] -side top -fill x -in $w.player
142  set spellstate normal
143  if {[lindex [sc_name read] 0] == 0} { set spellstate disabled}
144  foreach c {w b} name {White Black} {
145  pack $w.t$c -side top -fill x -in $w.player
146  ttk::label $w.t$c.label -text "$::tr($name) FIDE:" -width 14 -anchor w
147  pack $w.t$c.label -side left
148  foreach i $sTitleList {
149  set name [string toupper $i]
150  if {$i == "none"} { set name "-"}
151  ttk::checkbutton $w.t$c.b$i -text $name -variable sTitles($c:$i) -offvalue 0 -onvalue 1 -state $spellstate
152  pack $w.t$c.b$i -side left -padx "0 10"
153  }
154  }
155 
156  lower $w.player
157 
158  ttk::labelframe $w.tournement -text $::tr(Event)
159  pack $w.tournement -side top -fill x -pady 5
160  set f $w.eventsite
161  pack $f -side top -fill x -in $w.tournement -pady "0 3"
162  foreach i {Event Site} {
163  ttk::label $f.l$i -textvar ::tr(${i}:)
164  ttk::combobox $f.e$i -textvariable s$i -width 30
165  ::utils::history::SetCombobox HeaderSearch$i $f.e$i
166  bindFocusColors $f.e$i
167  }
168  pack $f.lEvent $f.eEvent -side left
169  pack $f.eSite -side right
170  pack $f.lSite -side right -padx "10 0"
171 
172  set f $w.eventround
173  pack $f -side top -fill x -in $w.tournement
174  lower $w.tournement
175  ## Setup date of Event
176  ttk::label $f.dl1 -text "$::tr(Event)\n$::tr(Date:)"
177  ttk::label $f.dl2 -text "-"
178  ttk::label $f.dl3 -text " "
179  ttk::entry $f.demin -textvariable sEventDateMin -width 10
180  button $f.deminCal -image tb_calendar -padx 0 -pady 0 -command {
181  regsub -all {[.]} $sEventDateMin "-" newdate
182  set ndate [::utils::date::chooser $newdate]
183  if {[llength $ndate] == 3} {
184  set sEventDateMin "[lindex $ndate 0].[lindex $ndate 1].[lindex $ndate 2]"
185  }
186  }
187  ttk::entry $f.demax -textvariable sEventDateMax -width 10
188  button $f.demaxCal -image tb_calendar -padx 0 -pady 0 -command {
189  regsub -all {[.]} $sEventDateMax "-" newdate
190  set ndate [::utils::date::chooser $newdate]
191  if {[llength $ndate] == 3} {
192  set sEventDateMax "[lindex $ndate 0].[lindex $ndate 1].[lindex $ndate 2]"
193  }
194  }
195  bindFocusColors $f.demin
196  bindFocusColors $f.demax
197  bind $f.demin <FocusOut> +checkDates
198  bind $f.demax <FocusOut> +checkDates
199  ttk::button $f.dlyear -textvar ::tr(YearToToday) -style Pad0.Small.TButton -command {
200  set sEventDateMin "[expr [::utils::date::today year]-1].[::utils::date::today month].[::utils::date::today day]"
201  set sEventDateMax [::utils::date::today]
202  }
203  ::utils::tooltip::Set $f.dlyear $::tr(YearToTodayTooltip)
204 
205  pack $f.dl1 $f.demin $f.deminCal $f.dl2 $f.demax $f.demaxCal $f.dl3 $f.dlyear -side left
206 
207  ttk::label $f.lRound -textvar ::tr(Round:)
208  ttk::entry $f.eRound -textvariable sRound -width 10
209  bindFocusColors $f.eRound
210  pack $f.eRound $f.lRound -side right
211 
212  set f $w.date
213  pack $f -side top -fill x -in $w.tournement -pady "0 3"
214  ## Setup Date of Game
215  ttk::label $f.l1 -text "$::tr(game)\n$::tr(Date:)"
216  ttk::label $f.l2 -text "-"
217  ttk::label $f.l3 -text " "
218  ttk::entry $f.emin -textvariable sDateMin -width 10
219  button $f.eminCal -image tb_calendar -padx 0 -pady 0 -command {
220  regsub -all {[.]} $sDateMin "-" newdate
221  set ndate [::utils::date::chooser $newdate]
222  if {[llength $ndate] == 3} {
223  set sDateMin "[lindex $ndate 0].[lindex $ndate 1].[lindex $ndate 2]"
224  }
225  }
226  ttk::entry $f.emax -textvariable sDateMax -width 10
227  button $f.emaxCal -image tb_calendar -padx 0 -pady 0 -command {
228  regsub -all {[.]} $sDateMax "-" newdate
229  set ndate [::utils::date::chooser $newdate]
230  if {[llength $ndate] == 3} {
231  set sDateMax "[lindex $ndate 0].[lindex $ndate 1].[lindex $ndate 2]"
232  }
233  }
234  bindFocusColors $f.emin
235  bindFocusColors $f.emax
236  bind $f.emin <FocusOut> +checkDates
237  bind $f.emax <FocusOut> +checkDates
238  ttk::button $f.lyear -textvar ::tr(YearToToday) -style Pad0.Small.TButton -command {
239  set sDateMin "[expr [::utils::date::today year]-1].[::utils::date::today month].[::utils::date::today day]"
240  set sDateMax [::utils::date::today]
241  }
242  ::utils::tooltip::Set $f.lyear $::tr(YearToTodayTooltip)
243 
244  pack $f.l1 $f.emin $f.eminCal $f.l2 $f.emax $f.emaxCal $f.l3 $f.lyear -side left
245 
246  ttk::labelframe $w.result -text $::tr(Result)
247  pack $w.result -side top -fill x -pady 5
248  pack $w.res -side top -fill x -in $w.result
249  ttk::label $w.res.l1 -textvar ::tr(Result:)
250  ttk::checkbutton $w.res.ewin -text "1-0 " -variable sResWin -offvalue "1" -onvalue ""
251  ttk::checkbutton $w.res.edraw -text "1/2-1/2 " -variable sResDraw -offvalue "=" -onvalue ""
252  ttk::checkbutton $w.res.eloss -text "0-1 " -variable sResLoss -offvalue "0" -onvalue ""
253  ttk::checkbutton $w.res.eother -text "* " -variable sResOther -offvalue "*" -onvalue ""
254  pack $w.res.l1 $w.res.ewin $w.res.edraw $w.res.eloss $w.res.eother -side left
255  lower $w.result
256 
257  ttk::label $w.gl.l1 -textvar ::tr(GameLength:)
258  ttk::label $w.gl.l2 -text "-"
259  ttk::label $w.gl.l3 -textvar ::tr(HalfMoves)
260  ttk::entry $w.gl.emin -textvariable sGlMin -justify right -width 4
261  ttk::entry $w.gl.emax -textvariable sGlMax -justify right -width 4
262  bindFocusColors $w.gl.emin
263  bindFocusColors $w.gl.emax
264  pack $w.gl -in $w.res -side right -fill x
265  pack $w.gl.l1 $w.gl.emin $w.gl.l2 $w.gl.emax $w.gl.l3 -side left
266 
267  ttk::label $w.ends.label -textvar ::tr(EndSideToMove)
268  ttk::checkbutton $w.ends.white -textvar ::tr(White) -variable sSideToMoveW -offvalue "" -onvalue w
269  ttk::checkbutton $w.ends.black -textvar ::tr(Black) -variable sSideToMoveB -offvalue "" -onvalue b
270  pack $w.ends.label $w.ends.white $w.ends.black -side left -padx "0 5"
271  pack $w.ends -side top -fill x -in $w.result
272 
273  pack $w.ano -side top -fill x
274  ttk::label $w.ano.a1 -textvar ::tr(Annotations:)
275  ttk::label $w.ano.a2 -textvar ::tr(Annotator:)
276  ttk::checkbutton $w.ano.an -textvar ::tr(Cmnts) -variable sAnnotated -offvalue 0 -onvalue 1
277  ttk::entry $w.ano.aname -textvariable sAnnotator -width 20
278  pack $w.ano.a1 $w.ano.an -side left -padx "0 5"
279  pack $w.ano.aname $w.ano.a2 -side right -padx "5 0"
280 
282 
283  ttk::label $w.eco.l1 -textvar ::tr(ECOCode:)
284  ttk::label $w.eco.l2 -text "-"
285  ttk::label $w.eco.l3 -text " "
286  ttk::entry $w.eco.emin -textvariable sEcoMin -width 5
287  ttk::entry $w.eco.emax -textvariable sEcoMax -width 5
288  bindFocusColors $w.eco.emin
289  bindFocusColors $w.eco.emax
290  ttk::button $w.eco.range -text "..." -style Pad0.Small.TButton -width 0 -command {
291  set tempResult [chooseEcoRange]
292  if {[scan $tempResult "%\[A-E0-9a-z\]-%\[A-E0-9a-z\]" sEcoMin_tmp sEcoMax_tmp] == 2} {
293  set sEcoMin $sEcoMin_tmp
294  set sEcoMax $sEcoMax_tmp
295  }
296  unset tempResult
297  }
298  ttk::checkbutton $w.eco.yes -variable sEco -onvalue Yes -offvalue No -textvar ::tr(GamesWithNoECO)
299  pack $w.eco -side top -fill x -pady "5 0"
300  pack $w.eco.l1 $w.eco.emin $w.eco.l2 $w.eco.emax -side left
301  pack $w.eco.range -side left -padx "5 10"
302  pack $w.eco.l3 $w.eco.yes -side left
303 
304  set f [ttk::frame $w.gnum]
305  pack $f -side top -fill x
306  ttk::label $f.l1 -textvar ::tr(GlistGameNumber:)
307  ttk::entry $f.emin -textvariable sGnumMin -width 8 -justify right
308  ttk::label $f.l2 -text "-" -font $regular
309  ttk::entry $f.emax -textvariable sGnumMax -width 8 -justify right
310  pack $f.l1 $f.emin $f.l2 $f.emax -side left
311  bindFocusColors $f.emin
312  bindFocusColors $f.emax
313  ttk::label $f.l3 -text " "
314  ttk::button $f.all -text [::utils::string::Capital $::tr(all)] -style Pad0.Small.TButton -command {set sGnumMin ""; set sGnumMax ""}
315  ttk::menubutton $f.first -style pad0.TMenubutton -textvar ::tr(First...) -menu $f.first.m
316  ttk::menubutton $f.last -style pad0.TMenubutton -textvar ::tr(Last...) -menu $f.last.m
317  menu $f.first.m
318  menu $f.last.m
319  foreach x {10 50 100 500 1000 5000 10000} {
320  $f.first.m add command -label $x \
321  -command "set sGnumMin 1; set sGnumMax $x"
322  $f.last.m add command -label $x \
323  -command "set sGnumMin -$x; set sGnumMax -1"
324  }
325  pack $f.l3 $f.all $f.first $f.last -side left -padx 2
326 
327  set f [ttk::frame $w.pgntext]
328  pack $f -side top -fill x
329  ttk::label $f.l1 -textvar ::tr(PgnContains:)
330  ttk::entry $f.e1 -textvariable sPgntext(1) -width 15
331  ttk::label $f.l2 -text "+" -font $regular
332  ttk::entry $f.e2 -textvariable sPgntext(2) -width 15
333  ttk::label $f.l3 -text "+" -font $regular
334  ttk::entry $f.e3 -textvariable sPgntext(3) -width 15
335  bindFocusColors $f.e1
336  bindFocusColors $f.e2
337  bindFocusColors $f.e3
338  pack $f.l1 $f.e1 $f.l2 $f.e2 $f.l3 $f.e3 -side left -pady "0 5"
339 
341 
342  ttk::button $w.flagslabel -textvar ::tr(FindGamesWith:) -style Pad0.Small.TButton -image tb_menu -compound left -command "
343  if {\$::sHeaderFlagFrame} {
344  set ::sHeaderFlagFrame 0
345  pack forget $w.flags
346  } else {
347  set ::sHeaderFlagFrame 1
348  pack $w.flags -side top -after $w.flagslabel -pady 5 -fill x
349  }
350  "
351  pack $w.flagslabel -side top -fill x -pady "5 5"
352 
353  ttk::frame $w.flags
354  if {$::sHeaderFlagFrame} {
355  pack $w.flags -side top -pady 5 -fill x
356  }
357 
358  set row 0
359  set col 0
360  foreach var [concat $::sHeaderFlagList $::sHeaderCustomFlagList] {
361  grid [ttk::label $w.flags.l$var -text [::tr $var] -font font_Small] -row $row -column $col -sticky w
362  incr col
363  grid [ttk::radiobutton $w.flags.yes$var -variable sHeaderFlags($var) -value yes -text $::tr(Yes)] -row $row -column $col
364  incr col
365  grid [ttk::radiobutton $w.flags.no$var -variable sHeaderFlags($var) -value no -text $::tr(No)] -row $row -column $col
366  incr col
367  grid [ttk::radiobutton $w.flags.both$var -variable sHeaderFlags($var) -value both -text $::tr(Both)] -row $row -column $col
368  incr col -3
369  incr row
370  if {$row == 12} {
371  set col 5
372  set row 0
373  }
374  }
375  grid columnconfigure $w.flags 4 -weight 1
376 
377  #TODO: ref_base should be used instead of curr_db
378  set ::curr_db [sc_base current]
379  foreach {tagname tagvalue} [sc_base extra $::curr_db] {
380  if { $tagvalue ne "" && [regexp {flag([1-6])} $tagname -> i] } {
381  $w.flags.lCustomFlag$i configure -text $tagvalue
382  }
383  }
384 
385  return "::search::headerGetOptions"
386 }
387 
388 proc ::search::headerGetOptions {{cmd ""}} {
389  if {$cmd eq "reset"} {
391  return
392  }
393 
394  ::utils::history::AddEntry HeaderSearchWhite $::sWhite
395  ::utils::history::AddEntry HeaderSearchBlack $::sBlack
396  ::utils::history::AddEntry HeaderSearchEvent $::sEvent
397  ::utils::history::AddEntry HeaderSearchSite $::sSite
398 
399  set options {header}
400  ::search::headerPlayerOptions options -white -welo -black -belo
401 
402  set invert_col 0
403  if {$::sIgnoreCol == "Yes" && [llength $options] > 1} { set invert_col 1}
404 
406  if {! $invert_col } {
407  return [list $options]
408  }
409 
410  set options2 {header}
411  ::search::headerPlayerOptions options2 -black -belo -white -welo
413  return [list $options $options2]
414 }
415 
416 proc ::search::getRange {var_min var_max cmd_min cmd_max} {
417  if {[set $var_min] ne ""} {
418  if {[set $var_max] ne ""} {
419  return [list [set $var_min] [set $var_max]]
420  }
421  return [list [set $var_min] [subst $cmd_max]]
422  } elseif {[set $var_max] ne ""} {
423  return [list [subst $cmd_min] [set $var_max]]
424  }
425  return {}
426 }
427 
428 proc ::search::headerPlayerOptions {dest_list white welo black belo} {
429  upvar $dest_list options
430 
431  if {$::sWhite ne ""} { lappend options $white $::sWhite}
432 
433  if {$::sBlack ne ""} { lappend options $black $::sBlack}
434 
435  set range [::search::getRange ::sWhiteEloMin ::sWhiteEloMax 0 "\[sc_info limit elo\]"]
436  if {$range ne ""} { lappend options $welo $range}
437 
438  set range [::search::getRange ::sBlackEloMin ::sBlackEloMax 0 "\[sc_info limit elo\]"]
439  if {$range ne ""} { lappend options $belo $range}
440 }
441 
442 ### Read values from header search dialog. Use empty string as "all"
443 proc ::search::getSearchOptions {dest_list} {
444  upvar $dest_list search
445 
446  if {$::sEvent ne ""} { lappend search "-event" $::sEvent}
447 
448  if {$::sSite ne ""} { lappend search "-site" $::sSite}
449 
450  if {$::sRound ne ""} { lappend search "-round" $::sRound}
451 
452  set range [::search::getRange ::sGnumMin ::sGnumMax 0 -1]
453  if {$range ne ""} { lappend search "-gnum" $range}
454 
455  set range [::search::getRange ::sGlMin ::sGlMax 0 999]
456  if {$range ne ""} { lappend search "-length" $range}
457 
458  set range [::search::getRange ::sDateMin ::sDateMax "1800.01.01" "\[sc_info limit year\].12.31"]
459  if {$range ne ""} { lappend search "-date" $range}
460 
461  set range [::search::getRange ::sEventDateMin ::sEventDateMax "1800.01.01" "\[sc_info limit year\].12.31"]
462  if {$range ne ""} { lappend search "-eventdate" $range}
463 
464  set range [::search::getRange ::sEloDiffMin ::sEloDiffMax "-\[sc_info limit elo\]" "\[sc_info limit elo\]"]
465  if {$range ne ""} {
466  lappend search "-delo" $range
467  if {$::sIgnoreCol == "Yes"} {
468  lassign $range elo_min elo_max
469  lappend search "-delo|" [list [expr -1 * $elo_max] [expr -1 * $elo_min]]
470  }
471  }
472 
473  set range [::search::getRange ::sEcoMin ::sEcoMax A00 E99]
474  if {$range ne ""} {
475  lappend search "-eco" $range
476  if {$::sEco eq "Yes"} { lappend search "-eco|" [list 0 0]}
477  }
478  if {$::sEco ne "Yes"} { lappend search "-eco!" [list 0 0]}
479 
480  set wtitles {}
481  set btitles {}
482  foreach i $::sTitleList {
483  if $::sTitles(w:$i) { lappend wtitles $i}
484  if $::sTitles(b:$i) { lappend btitles $i}
485  }
486  if {[llength $wtitles] != 8} { lappend search -wtitles $wtitles}
487  if {[llength $btitles] != 8} { lappend search -btitles $btitles}
488 
489  if {$::sSideToMoveW eq "" || $::sSideToMoveB eq ""} {
490  lappend search -toMove "$::sSideToMoveW$::sSideToMoveB"
491  }
492 
493  if {$::sAnnotated} { lappend search "-annotated" $::sAnnotated}
494 
495  if {$::sAnnotator ne ""} { lappend search "-annotator" $::sAnnotator}
496 
497  global sHeaderFlags
498  global sResWin sResLoss sResDraw sResOther sPgntext
499 
500  set sPgnlist {}
501  foreach i {1 2 3} {
502  set temp [string trim $sPgntext($i)]
503  if {$temp != ""} { lappend sPgnlist $temp}
504  }
505 
506  set flagsYes ""
507  set flagsNo ""
508  set idx -1
509  foreach i [ concat $::sHeaderFlagList $::sHeaderCustomFlagList] {
510  incr idx
511  if {$i == "Comments"} { continue}
512  if {$i == "Variations"} { continue}
513  if {$i == "Annotations"} { continue}
514 
515  if { $sHeaderFlags($i) == "yes" } {
516  append flagsYes [lindex $::sHeaderFlagChars $idx]
517  } elseif { $sHeaderFlags($i) == "no" } {
518  append flagsNo [lindex $::sHeaderFlagChars $idx]
519  }
520  }
521 
522  set results ""
523  append results $sResWin $sResDraw $sResLoss $sResOther
524  foreach { i j} { -result! results -flag flagsYes -flag! flagsNo -pgn sPgnlist} {
525  if { [llength [set $j]] > 0 } {
526  lappend search $i [set $j]
527  }
528  }
529  set fCounts(Variations) "-n_variations"
530  set fCountsV(Variations) ""
531  set fCounts(Comments) "-n_comments"
532  set fCountsV(Comments) ""
533  set fCounts(Annotations) "-n_nags"
534  set fCountsV(Annotations) ""
535  foreach i {"Variations" "Comments" "Annotations"} {
536  if { $sHeaderFlags($i) == "yes" } {
537  append fCounts($i) "!"
538  set fCountsV($i) "0"
539  lappend search $fCounts($i) $fCountsV($i)
540  } elseif { $sHeaderFlags($i) == "no" } {
541  set fCountsV($i) "0"
542  lappend search $fCounts($i) $fCountsV($i)
543  }
544  }
545 }
546 
547 proc ::search::header::save {} {
548  global sWhite sBlack sEvent sSite sRound sAnnotator sAnnotated sDateMin sDateMax sIgnoreCol
549  global sWhiteEloMin sWhiteEloMax sBlackEloMin sBlackEloMax
550  global sEloDiffMin sEloDiffMax sGlMin sGlMax
551  global sEco sEcoMin sEcoMax sHeaderFlags sSideToMoveW sSideToMoveB
552  global sResWin sResLoss sResDraw sResOther sPgntext
553 
554  set ftype { { "Scid SearchOptions files" {".sso"} } }
555  set fName [tk_getSaveFile -initialdir [pwd] -filetypes $ftype -title "Create a SearchOptions file"]
556  if {$fName == ""} { return}
557 
558  if {[string compare [file extension $fName] ".sso"] != 0} {
559  append fName ".sso"
560  }
561 
562  if {[catch {set searchF [open [file nativename $fName] w]}]} {
563  tk_messageBox -title "Error: Unable to open file" -type ok -icon error \
564  -message "Unable to create SearchOptions file: $fName"
565  return
566  }
567  puts $searchF "\# SearchOptions File created by Scid $::scidVersion"
568  puts $searchF "set searchType Header"
569  getSearchEntries
570 
571  # First write the regular variables:
572  foreach i {sWhite sBlack sEvent sSite sRound sAnnotator sAnnotated sDateMin sDateMax sResWin
573  sResLoss sResDraw sResOther sWhiteEloMin sWhiteEloMax sBlackEloMin
574  sBlackEloMax sEcoMin sEcoMax sEloDiffMin sEloDiffMax
575  sIgnoreCol sSideToMoveW sSideToMoveB sGlMin sGlMax ::search::filter::operation} {
576  puts $searchF "set $i [list [set $i]]"
577  }
578  # Now write the array values:
579  foreach i [array names sHeaderFlags] {
580  puts $searchF "set sHeaderFlags($i) [list $sHeaderFlags($i)]"
581  }
582  foreach i [array names sPgntext] {
583  puts $searchF "set sPgntext($i) [list $sPgntext($i)]"
584  }
585 
586  tk_messageBox -type ok -icon info -title "Search Options saved" \
587  -message "Header search options saved to: $fName"
588  close $searchF
589 }
590 
591 ##############################
592 ### Selecting common ECO ranges
593 
594 set scid_ecoRangeChosen ""
595 set ecoCommonRanges {}
596 proc chooseEcoRange {} {
597  global ecoCommonRanges scid_ecoRangeChosen
598  set ecoCommonRanges [ list \
599  "A04-A09 [tr Reti]: [trans 1.Nf3]" \
600  "A10-A39 [tr English]: 1.c4" \
601  "A40-A49 1.d4, [tr d4Nf6Miscellaneous]" \
602  "A45l-A45z [tr Trompowsky]: [trans [list 1.d4 Nf6 2.Bg5]]" \
603  "A51-A52 [tr Budapest]: [trans [list 1.d4 Nf6 2.c4 e5]]" \
604  "A53-A55 [tr OldIndian]: [trans [list 1.d4 Nf6 2.c4 d6]]" \
605  "A57-A59 [tr BenkoGambit]: [trans [list 1.d4 Nf6 2.c4 c5 3.d5 b5]]" \
606  "A60-A79 [tr ModernBenoni]: [trans [list 1.d4 Nf6 2.c4 c5 3.d5 e6]]" \
607  "A80-A99 [tr DutchDefence]: 1.d4 f5" \
608  "____________________________________________________________" \
609  "B00-C99 1.e4" \
610  "B01-B01 [tr Scandinavian]: 1.e4 d5" \
611  "B02-B05 [tr AlekhineDefence]: [trans [list 1.e4 Nf6]]" \
612  "B07-B09 [tr Pirc]: 1.e4 d6" \
613  "B10-B19 [tr CaroKann]: 1.e4 c6" \
614  "B12i-B12z [tr CaroKannAdvance]: 1.e4 c6 2.d4 d5 3.e5" \
615  "B20-B99 [tr Sicilian]: 1.e4 c5" \
616  "B22-B22 [tr SicilianAlapin]: 1.e4 c5 2.c3" \
617  "B23-B26 [tr SicilianClosed]: [trans [list 1.e4 c5 2.Nc3]]" \
618  "B30-B39 [tr Sicilian]: [trans [list 1.e4 c5 2.Nf3 Nc6]]" \
619  "B40-B49 [tr Sicilian]: [trans [list 1.e4 c5 2.Nf3 e6]]" \
620  "B50-B59 [tr SicilianRauzer]: [trans [list 1.e4 c5 2.Nf3 d6 ... 5.Nc3 Nc6]]" \
621  "B70-B79 [tr SicilianDragon]: [trans [list 1.e4 c5 2.Nf3 d6 ... 5.Nc3 g6]]" \
622  "B80-B89 [tr SicilianScheveningen]: [trans [list 1.e4 c5 2.Nf3 d6 ... 5.Nc3 e6]]" \
623  "B90-B99 [tr SicilianNajdorf]: [trans [list 1.e4 c5 2.Nf3 d6 ... 5.Nc3 a6]]" \
624  "____________________________________________________________" \
625  "C00-C19 [tr FrenchDefence]: 1.e4 e6" \
626  "C02-C02 [tr FrenchAdvance]: 1.e4 e6 2.d4 d5 3.e5" \
627  "C03-C09 [tr FrenchTarrasch]: [trans [list 1.e4 e6 2.d4 d5 3.Nd2]]" \
628  "C15-C19 [tr FrenchWinawer]: [trans [list 1.e4 e6 2.d4 d5 3.Nc3 Bb4]]" \
629  "C20-C99 [tr OpenGame]: 1.e4 e5" \
630  "C25-C29 [tr Vienna]: [trans [list 1.e4 e5 2.Nc3]]" \
631  "C30-C39 [tr KingsGambit]: 1.e4 e5 2.f4" \
632  "C42-C43 [tr RussianGame]: [trans [list 1.e4 e5 2.Nf3 Nf6]]" \
633  "C44-C49 [tr OpenGame]: [trans [list 1.e4 e5 2.Nf3 Nc6]]" \
634  "C50-C59 [tr ItalianTwoKnights]: 1.e4 e5 2.Nf3 Nc6 3.Bc4]]" \
635  "C60-C99 [tr Spanish]: [trans [list 1.e4 e5 2.Nf3 Nc6 3.Bb5]]" \
636  "C68-C69 [tr SpanishExchange]: [trans [list 3.Bb5 a6 4.Bxc6]]" \
637  "C80-C83 [tr SpanishOpen]: [trans [list 3.Bb5 a6 4.Ba4 Nf6 5.O-O Nxe4]]" \
638  "C84-C99 [tr SpanishClosed]: [trans [list 3.Bb5 a6 4.Ba4 Nf6 5.O-O Be7]]" \
639  "____________________________________________________________" \
640  "D00-D99 [tr Queen's Pawn]: 1.d4 d5" \
641  "D10-D19 [tr Slav]: 1.d4 d5 2.c4 c6" \
642  "D20-D29 [tr QGA]: 1.d4 d5 2.c4 dxc4" \
643  "D30-D69 [tr QGD]: 1.d4 d5 2.c4 e6" \
644  "D35-D36 [tr QGDExchange]: 1.d4 d5 2.c4 e6 3.cxd5 exd5" \
645  "D43-D49 [tr SemiSlav]: [trans [list 3.Nc3 Nf6 4.Nf3 c6]]" \
646  "D50-D69 [tr QGDwithBg5]: [trans [list 1.d4 d5 2.c4 e6 3.Nc3 Nf6 4.Bg5]]" \
647  "D60-D69 [tr QGDOrthodox]: [trans [list 4.Bg5 Be7 5.e3 O-O 6.Nf3 Nbd7]]" \
648  "D70-D99 [tr Grunfeld]: [trans [list 1.d4 Nf6 2.c4 g6 with 3...d5]]" \
649  "D85-D89 [tr GrunfeldExchange]: [trans [list 3.Nc3 d5 4.e4 Nxc3 5.bxc3]]" \
650  "D96-D99 [tr GrunfeldRussian]: [trans [list 3.Nc3 d5 4.Nf3 Bg7 5.Qb3]]" \
651  "____________________________________________________________" \
652  "E00-E09 [tr Catalan]: [trans [list 1.d4 Nf6 2.c4 e6 3.g3/...]]" \
653  "E02-E05 [tr CatalanOpen]: [trans [list 3.g3 d5 4.Bg2 dxc4]]" \
654  "E06-E09 [tr CatalanClosed]: [trans [list 3.g3 d5 4.Bg2 Be7]]" \
655  "E12-E19 [tr QueensIndian]: [trans [list 1.d4 Nf6 2.c4 e6 3.Nf3 b6]]" \
656  "E20-E59 [tr NimzoIndian]: [trans [list 1.d4 Nf6 2.c4 e6 3.Nc3 Bb4]]" \
657  "E32-E39 [tr NimzoIndianClassical]: [trans [list 4.Qc2]]" \
658  "E40-E59 [tr NimzoIndianRubinstein]: 4.e3" \
659  "E60-E99 [tr KingsIndian]: [trans [list 1.d4 Nf6 2.c4 g6]]" \
660  "E80-E89 [tr KingsIndianSamisch]: 4.e4 d6 5.f3" \
661  "E90-E99 [tr KingsIndianMainLine]: [trans [list 4.e4 d6 5.Nf3]]"]
662 
663  if {[winfo exists .ecoRangeWin]} { return}
664  set w .ecoRangeWin
665  toplevel $w
666  wm title $w "Scid: Choose ECO Range"
667  wm minsize $w 30 5
668 
669  listbox $w.list -yscrollcommand "$w.ybar set" -height 20 -width 60 -background white -setgrid 1
670  foreach i $ecoCommonRanges { $w.list insert end $i}
671  ttk::scrollbar $w.ybar -command "$w.list yview" -takefocus 0
672  pack [ttk::frame $w.b] -side bottom -fill x
673  pack $w.ybar -side right -fill y
674  pack $w.list -side left -fill both -expand yes
675 
676  ttk::button $w.b.ok -text "OK" -command {
677  set sel [.ecoRangeWin.list curselection]
678  if {[llength $sel] > 0} {
679  set scid_ecoRangeChosen [lindex $ecoCommonRanges [lindex $sel 0]]
680  set ::sEco No
681  }
682  destroy .ecoRangeWin
683  }
684  ttk::button $w.b.cancel -text $::tr(Cancel) -command "destroy $w"
685  pack $w.b.cancel $w.b.ok -side right -padx 5 -pady 2
686  bind $w <Escape> "
687  set scid_ecoRangeChosen {}
688  grab release $w
689  focus .
690  destroy $w
691  break"
692  bind $w <Return> "$w.b.ok invoke; break"
693  bind $w.list <Double-ButtonRelease-1> "$w.b.ok invoke; break"
694  focus $w.list
695  grab $w
696  tkwait window $w
697  return $scid_ecoRangeChosen
698 }
699 
700 ###
701 ### End of file: search.tcl
702