Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
end.tcl
Go to the documentation of this file.
1 # end.tcl: part of Scid.
2 # Copyright (C) 2000-2003 Shane Hudson.
3 
4 if { ! [file isdirectory $::scidBooksDir]} {
5  tk_messageBox -title "Scid" -type ok -icon warning -message "Books directory not found"
6 }
7 
8 
9 # findNovelty:
10 # Searches the for first position in the current game not
11 # found in the selected database.
12 
13 set noveltyOlder 0
14 
15 proc findNovelty {} {
16  global noveltyBase noveltyOlder
17  set noveltyBase [sc_base current]
18  set w .noveltyWin
19  if {[winfo exists $w]} {
21  return
22  }
24  wm title $w "Scid: $::tr(FindNovelty)"
25 
26  pack [ttk::frame $w.help] -side top -fill x
27  ttk::label $w.help.text -wraplength 3i -justify left -text $::tr(NoveltyHelp)
28  pack $w.help.text -side left -fill x -expand yes
29  ttk::labelframe $w.bases -text $::tr(Database)
30  pack $w.bases -side top -fill x -pady 5
31 
32  pack [ttk::frame $w.bases.del]
33 
34  ttk::labelframe $w.which -text $::tr(TwinsWhich)
35  pack $w.which -side top -fill x -pady 5
36  ttk::radiobutton $w.which.all -text $::tr(SelectAllGames) \
37  -variable noveltyOlder -value 0
38  ttk::radiobutton $w.which.older -text $::tr(SelectOlderGames) \
39  -variable noveltyOlder -value 1
40  pack $w.which.all $w.which.older -side top -anchor w -fill x
41 
42  pack [ttk::frame $w.b] -side top -fill x
43  dialogbutton $w.b.go -text $::tr(FindNovelty) -command {
44  destroy .noveltyWin
45  progressWindow "Scid" "$::tr(FindNovelty)" $::tr(Cancel)
46  if {$noveltyOlder} {
47  set err [catch {sc_game novelty -older $noveltyBase} result]
48  } else {
49  set err [catch {sc_game novelty $noveltyBase} result]
50  }
51  closeProgressWindow
52  if {$err} {
53  ERROR::MessageBox
54  } else {
55  if {$result < 0} {
56  tk_messageBox -message "[tr NoveltyNone]"
57  }
58  }
59  updateBoard -pgn
60  }
61  dialogbutton $w.b.close -textvar ::tr(Close) -command {
62  catch {destroy .noveltyWin}
63  }
64  packdlgbuttons $w.b.close $w.b.go
65  wm resizable $w 0 0
66  focus $w.b.go
67  bind $w <KeyPress-1> "$w.b1 invoke"
68  bind $w <KeyPress-2> "$w.b2 invoke"
69  bind $w <KeyPress-3> "$w.b3 invoke"
70  bind $w <KeyPress-4> "$w.b4 invoke"
72 }
73 
74 proc updateNoveltyWin {} {
75  set w .noveltyWin
76  if {! [winfo exists $w]} { return}
77  $w.which.older configure -text "$::tr(SelectOlderGames) (< [sc_game info date])"
78  catch { destroy $w.bases.del}
79  pack [frame $w.bases.del] -anchor w
80  foreach i [sc_base list] {
81  set name [file tail [sc_base filename $i]]
82  set ng [::utils::thousands [sc_base numGames $i]]
83  set txt "Base $i: $name ($ng $::tr(games))"
84  ttk::radiobutton $w.bases.del.b$i -text "$txt" -variable noveltyBase -value $i -underline 5
85  if {$ng == 0} { $w.bases.del.b$i configure -state disabled}
86  pack $w.bases.del.b$i -side top -anchor w -fill x
87  }
88 }
89 
90 set merge(ply) 40
91 
92 # mergeGame:
93 # Produces a dialog for the user to merge a selected game into
94 # the current game.
95 #
96 proc mergeGame {base gnum} {
97  global merge
98 
99  sc_game push copy
100  set err [catch {sc_game merge $base $gnum} result]
101  sc_game pop
102  if {$err} {
103  tk_messageBox -title "Scid" -type ok -icon info \
104  -message "Unable to merge the selected game:\n$result"
105  return
106  }
107  set merge(base) $base
108  set merge(gnum) $gnum
109  set w .mergeDialog
111  wm title $w "Scid: $::tr(MergeGame)"
112  bind $w <Escape> "$w.b.cancel invoke"
113  bind $w <F1> {helpWindow GameList Browsing}
114  ttk::label $w.title -text $::tr(Preview:) -font font_Bold -anchor center
115  pack $w.title -side top -fill x
116  pack [ttk::frame $w.b] -side bottom -fill x
117  ttk::frame $w.f
118  text $w.f.text -background white -wrap word -width 60 -height 20 \
119  -font font_Small -yscrollcommand "$w.f.ybar set"
120  ttk::scrollbar $w.f.ybar -takefocus 0 -command "$w.f.text yview"
121  event generate $w.f.text <ButtonRelease-1>
122  pack $w.f.ybar -side right -fill y
123  pack $w.f.text -side left -fill both -expand yes
124  pack $w.f -fill both -expand yes
125  set small font_Small
126  ttk::label $w.b.label -text "Up to move:" -font $small
127  pack $w.b.label -side left
128  foreach i {5 10 15 20 25 30 35 40 500} {
129  if {$i != 500} {
130  set label $i
131  set label_width 3
132  } else {
133  set label [::utils::string::Capital $::tr(all)]
134  set label_width [string length $label]
135  }
136  ttk::button $w.b.m$i -text $label -width $label_width -padding 0 \
137  -command "updateMergeGame $w $i"
138  pack $w.b.m$i -side left
139  }
140  dialogbutton $w.b.ok -text "OK" -command {
141  undoFeature save
142  sc_game merge $merge(base) $merge(gnum) $merge(ply)
143  catch {grab release .mergeDialog}
144  destroy .mergeDialog
145  updateBoard -pgn
146  }
147  dialogbutton $w.b.cancel -text $::tr(Cancel) \
148  -command "catch {grab release $w}; destroy $w"
149  packbuttons right $w.b.cancel $w.b.ok
150  grab $w
151  updateMergeGame $w [expr $merge(ply) / 2]
152 }
153 
154 proc updateMergeGame {{w} {n_moves}} {
155  global merge
156  if {! [winfo exists $w]} { return}
157 
158  # Update widgets
159  set widget [expr $merge(ply) / 2]
160  $w.b.m$widget state !pressed
161  $w.b.m$n_moves state pressed
162  set merge(ply) [expr {$n_moves * 2}];
163 
164  sc_game push copy
165  sc_game merge $merge(base) $merge(gnum) $merge(ply)
166  set pgn [sc_game pgn -indentV 1 -short 1 -width 60]
167  sc_game pop
168  $w.f.text configure -state normal
169  $w.f.text tag configure red -foreground darkRed
170  $w.f.text tag configure blue -foreground darkBlue
171  $w.f.text delete 1.0 end
172  foreach line [split $pgn "\n"] {
173  if {[string index $line 0] == " "} {
174  $w.f.text insert end $line blue
175  } else {
176  $w.f.text insert end $line
177  }
178  $w.f.text insert end "\n"
179  }
180  $w.f.text tag add red 1.0 4.0
181  #$w.f.text insert end $pgn
182  $w.f.text configure -state disabled
183 }
184 
185 # setExportText:
186 # Allows the user to modify the text printed at the start and end of a
187 # file for a particular export format
188 #
189 proc setExportText {exportType} {
190  global exportStartFile exportEndFile
191 
192  switch -- $exportType {
193  "PGN" {
194  set title "Set PGN file export text"
195  }
196  "HTML" {
197  set title "Set HTML file export text"
198  }
199  "LaTeX" {
200  set title "Set LaTeX file export text"
201  }
202  default {
203  return
204  }
205  }
206 
207  set w .setExportText$exportType
208  if {[winfo exists $w]} { return}
210  wm title $w "Scid: $title"
211 
212  ttk::frame $w.buttons
213  pack $w.buttons -side bottom -fill x -anchor e
214 
215  set pane [::utils::pane::Create $w.pane start end 500 400]
216  ::utils::pane::SetRange $w.pane 0.3 0.7
217  pack $pane -side top -expand true -fill both
218  foreach f [list $pane.start $pane.end] type {start end} {
219  ttk::label $f.title -font font_Bold -text "Text at $type of $exportType file:"
220  text $f.text -wrap none -background white \
221  -yscroll "$f.ybar set" -xscroll "$f.xbar set"
222  ttk::scrollbar $f.ybar -orient vertical -command "$f.text yview"
223  ttk::scrollbar $f.xbar -orient horizontal -command "$f.text xview"
224  bind $f.text <FocusIn> {%W configure -background lightYellow}
225  bind $f.text <FocusOut> {%W configure -background white}
226  grid $f.title -row 0 -column 0 -sticky w
227  grid $f.text -row 1 -column 0 -sticky nesw
228  grid $f.ybar -row 1 -column 1 -sticky nesw
229  grid $f.xbar -row 2 -column 0 -sticky nesw
230  grid rowconfig $f 1 -weight 1 -minsize 0
231  grid columnconfig $f 0 -weight 1 -minsize 0
232  }
233 
234  $pane.start.text insert end $exportStartFile($exportType)
235  $pane.end.text insert end $exportEndFile($exportType)
236 
237  ttk::button $w.buttons.default -text "Reset to Default" -command "
238  $pane.start.text delete 1.0 end
239  $pane.start.text insert end \$default_exportStartFile($exportType)
240  $pane.end.text delete 1.0 end
241  $pane.end.text insert end \$default_exportEndFile($exportType)
242  "
243  dialogbutton $w.buttons.ok -text "OK" -command "
244  set exportStartFile($exportType) \[$pane.start.text get 1.0 end-1c\]
245  set exportEndFile($exportType) \[$pane.end.text get 1.0 end-1c\]
246  focus .
247  destroy $w
248  "
249  dialogbutton $w.buttons.cancel -text $::tr(Cancel) -command "focus .; destroy $w"
250  pack $w.buttons.default -side left -padx 5 -pady 2
251  packdlgbuttons $w.buttons.cancel $w.buttons.ok
252  focus $pane.start.text
253 }
254 
255 image create photo htmldiag0 -data {
256  R0lGODdhbgBkAIAAAAAAAP///ywAAAAAbgBkAAAC/oyPqcvtD6OctNqLs968+w+G4kiW5omm
257  6moAgQu/ckzPdo3fes7vfv5wsYQtBFF2OCqNzCPrs4xEi0mQEyWcApxbqhfpvYa2ZCNZeQ4y
258  k122YgqGNs7oMtu+aH9f6XT1vydm5ddCyIenlkB3KAgnePFIJzm5yECkRVmpuPbokflpaLl2
259  eKeHCNcRCQo6F3e52qY3Gve04QhbJkvrGYQb+jbrB8sHaJPi25mnGItLvDmRnLwnCpH1luUb
260  WGwpLdUsIdaFHLtdHe09bM45Lkw9p4uRXfHKbseFntibnk9fT/4XDR6kb+BKsfrkrFuhc+b2
261  OYhh0J+1Z+8U6ltVMGIm/kaTpnnL95DgQzPpMC6RJtCCPArMOmqsNDFjq4YYq5lZGKokxZEc
262  Vtok5pIkwl2p0NXsZZDUsmH3fmpIuWxeUKEHy828yo0dT6p5sk3sZrGrP6dWx3kMCRKYykhE
263  xcpD1fWpxK1tOX4LK9OtVneuliKjAnEEIqkMA9UrgjctTokCY+4a29fvL6OM2ZabW3co1peH
264  rwVb3DmM5lpSRlV2DHryrGPFEidqShrS59azz2Zw/TTyF0e168aG1ps3bRG4bz8pvqmH8h/M
265  lztvDj0wVuG7g/sW3Bv48Orbr7Purky3eOpgkMsenxcuX/XHs3NzzzG8NsJQ38EnG2Uq+rWa
266  /s7bVrvfRtwBxhIlLHWnEHUCklegfumtpgx5AloHjYHAMTjdahbeB46D+EG4Hoj68YaXh3Sx
267  B9IVrADo3TUTHmjVTHA5pFuCR70G4oeSaYZiRTemyGJcw72lIWWj2TckjKLRKN5FKypZHj/B
268  iBQZWFS6g2GIVI3Wo15HApljFTMSlKWLP4oyo45L8himkxuq2eJ+nKV0UoUvgvlfhmb2x2FI
269  JsL505hPDmjjoDx1qeWWEyK655d6tunMNGbt5N2kaF0Wlop7DejnX9qRJGWj++TnJpMUhVPf
270  bJhBOqehWqompmmQgbejT8Bgkup4s8aZ2pU71VGYK4xVp8qqLAJriREXw1LqpaV0xXeoqJ4C
271  Uuyuz2g62KvL5tnqmb8uhhS128Imra03iZvtsz2xikU8CFLInXkqvVsavZwyekKZTcArZ5Pt
272  6vutvf3GBjC7VrRX1HMKR8fwwg4bo26+/Eq4729FCUyxHEPcO7FpFtvSscC8DJExx9vI+3G/
273  JfNK1ncqh4zybyuvLEEBADs=
274 }
275 
276 image create photo htmldiag1 -data {
277  R0lGODdhbgBkAIQAAAAAAAsLCxYWFiAgICsrKzY2NkBAQEtLS1VVVWBgYGtra3V1dYCAgIuL
278  i5WVlaCgoKqqqrW1tcDAwMrKytXV1eDg4Orq6vX19f//////////////////////////////
279  /ywAAAAAbgBkAAAF/iAmjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IJBGAYTqb0Kc0
280  Sp1aq9irNst9vphLkYWAEFEEkFGEIkIQLJhxGUMhsDGQ9wis7MnNaCducH90diJ5cBgVQ3xC
281  AIVnaSMLiHqRh3h6GAgNUCsRBgd3NRIAp3ymqKcMe6gSKQdzkiIScAYKJJh3iW1zLBWoAzGO
282  GKqnI8eorSKrsCcAk7QiDG8GAA4kjIa8mwi/xSbKN8oS5g6rpwnm5SvTcAwAA6gFtrrbvZy/
283  LgWnk18llKUbSPCZCSbTIBjAEIGgvAQPSEjwNscCrHAmCJzaN0Ogw48GTSQUwMaCgFMH/lAJ
284  YJBAwEpFI76JIRChBYJVAmAU8/ixIAoABiZBIDlCAQACFfrJY2Qh3oAJMSsSmIRxBIR0w2zc
285  7PmRYwlFQ0lNOLXQwqoEjCaczEZn5j8VFU7i1CnoFLu7eM1tVAEmLIl5AARYMJuu1RkAv8a8
286  rYpBabocKV0AONDCL0MMD7juPTwpKCJmKMYSpHsiHoPTqFOnBgD6p2UEEa8JANyVzklSeIhW
287  dfwYRzzNy1gguDOoCS+uZdARsEo0BYWPpE38Bs56BZ/iwQrcudazZr+IEZp/KjF9YI7ymlur
288  KN6YrEa5HwUHG1bhzrYT3EcDLE2dlXVOmzTUX3AJAEAKAq1g/pSfeb4NqN4JCmwS14DCMARA
289  JQDCZMKCvUmGAnpcPVjChYqMgdxHbMijiSIYgYjKeQ7CoJEBGhGUy0etXFPBYKBAt590MfIV
290  h0XVmVVAjQQcABVPZGFQYE1xXIQCfAMsEIE5MPYn4ldvPCdBeNk4RUID8WFgWhwEeJLCAqew
291  NUNV8Ui25R6yiEDAAC6J0A9UI/Bm3pl1jldCMMtFkAB3OJgo2SYp/HMYA3VEQ4KAKJpC2X0q
292  sEkbAyGxEI6JQBkg6qikjnoKoweJsOMiFBAKJSBc6bUQCYzFQ+YpA8xaQ0oUouROJiiEp5le
293  GFIQkQrTCWDAadGJQRuFA2hIax28/qg5ggV+gmSKYQLUxBiZNOUAaq+nShtTN4owVSNwFpDZ
294  ylQsmGJLA4fq2oIjLlIoIh/5DIeBUf2ZCUBNrzLR1IIDaPQsYyzkGyQK/ZYRzIBOGmiCSQH/
295  KDC5q+y7oi8i3KrlPFYlyKZmVc7ZMMcdQ0zRCBOUKvPMuCDSHIcEudlsECSCHOUNzU2mLAMN
296  5IVlHzLIhOZbM2CKKQ8M7wCG0orZTNwlZAAilHiCIu3117R2IfYWZI9tdtlo0xBJILldTUjW
297  3FhirhFrb42bh3VbLYICB7w9Syb5MBK1DgbDPdIducCQd9snUKAmtXK3YW0Ri1smw2SzsG05
298  HUTfB/nH/vo088IDpzUwN1+BHk7C3SxIo3lzjGzlDwYXAP6y4usGxvoKrtutKieDh22b75xU
299  IJpKcOBzu+grp1MAaaoXL5oM0SPwPIgGRSxGpyrgHHwJ1V+PzBfV63E8KttEcPsY3rYAYlaS
300  lQ/H9DB4xjgGCyygyAPwAWUu1fByQVMG4pUV2M8y+dvfSXQCFq7F4QG5UwlEKCGVfzCsAg3o
301  3yqqxCfrNPBuFoDgi2RgmQTAQVhceYouAtg8zRTgaY1qjgkZokG6vKYVlAIOn6qGhwShAGDU
302  EYyQbmghBr3gNXpYWArtRLwTTGxACeBdc4qjxO81w18ZMkavTqi3rlGjV8tJ/gFi3KZF/SRt
303  ExSQWTqUVar7bO4EDyhVBOVRKsrYBI1qtOInisOjg6zCXiWwjOBa4BGVpSqLfRyRHtuANfuQ
304  Ih2AZA5xDCmRgVDSBHzMRH1coZMI+c0MmcjhKdRFvOIED4j06CTW/nYHAcVAf2hi5QjmWIkH
305  lBJVK3hiOjrYAljuYpbj81AsQUmK5wwkJ5JkJEwGl68oCvOXZhgh7mRJCYdACYmE4B4KqhiY
306  GEBTBCfTIyQMB7iaeK864SHjGDwRNV0OBIY/gSYEzClNF6TOdnD4yEIeoE64xasn2kTBPdHV
307  hHp6Shr4tJNDMKTMYTLPOT3ZHTQQSlAMrGsGn8tH/hHXeKBVxkB26QgjDDLKKErRhaTSoqU2
308  PkmHiAzOna8ACEpLUKMYzDQOETgNQQZwGoOs7VUoqEBOC0SQBHAKniJJKE51Gsx7YbEXFiAq
309  cFYiArZMAyMUyFZPCsDLgzz1ElJdBQ2gOkfN/GIaKDhMr4DaKKw5hDT5EBmFoIJWL/KqV8iE
310  RuQwINcOHZFR50wPBg4glC2xDAAB3SsGAquTfKSBdKqJrGQ5RQK/hGOymFUNUqOxicdi9pWK
311  QEDicPBGIsCSE6PFwXUqwoALiCACbmrAJJrCJwq0tote/MFqxXBbhugsaRXsYiYz10QlALCU
312  OwPCImmwXLqk7blniy50waebXN1qTbgeHd5elfZQsN1Afg5NyPpOJ7UiGOh1/STudqWSIu/i
313  AL0Nrdz6WMgz815zitkVb2iD21331gCb4dXcfJlW3zAAWL77dYsZBunf/+KXpfr1GQ/rgNTy
314  LuHBARbKgInZ3wbDYBvDvS7ojsvhMJg4xNodMX8/12EPvwDFEQ7d0kqMgMQSzrwwFnCCZxy3
315  LDbXxfnVsYQD+Dn2PMK8M1GvihXcYyP/2MUIHjJF40veGy8hyjKecCYyKSUYhAAAOw==
316 }
317 
318 # exportOptions:
319 # Prompts the user to select exporting options.
320 #
321 proc exportOptions {exportType} {
322  global exportFlags
323 
324  set w .exportFlagsWin
325  set exportFlags(ok) -1
327  wm title $w "Scid: [tr OptionsExport]"
328  # wm transient $w .
329  wm protocol $w WM_DELETE_WINDOW { }
330  bind $w <Escape> "$w.b.cancel invoke"
331  bind $w <Return> "$w.b.ok invoke"
332  bind $w <F1> {helpWindow Export}
333 
334  pack [ttk::frame $w.o] -side top -fill x
335  ttk::checkbutton $w.o.append -variable exportFlags(append) -offvalue 0 -onvalue 1 -textvar ::tr(AddToExistingFile)
336  ttk::checkbutton $w.o.comments -variable exportFlags(comments) -offvalue 0 -onvalue 1 -textvar ::tr(ExportComments)
337  ttk::checkbutton $w.o.stripMarks -variable exportFlags(stripMarks) -offvalue 0 -onvalue 1 -textvar ::tr(ExportStripMarks)
338  ttk::checkbutton $w.o.indentc -variable exportFlags(indentc) -offvalue 0 -onvalue 1 -textvar ::tr(IndentComments)
339  ttk::checkbutton $w.o.vars -variable exportFlags(vars) -offvalue 0 -onvalue 1 -textvar ::tr(ExportVariations)
340  ttk::checkbutton $w.o.indentv -variable exportFlags(indentv) -offvalue 0 -onvalue 1 -textvar ::tr(IndentVariations)
341  ttk::checkbutton $w.o.column -variable exportFlags(column) -offvalue 0 -onvalue 1 -textvar ::tr(ExportColumnStyle)
342  ttk::checkbutton $w.o.symbols -variable exportFlags(symbols) -offvalue 0 -onvalue 1 -text "$::tr(ExportSymbolStyle) ! +="
343  grid $w.o.append -row 0 -column 0 -sticky w
344  grid $w.o.comments -row 1 -column 0 -sticky w
345  grid $w.o.stripMarks -row 2 -column 0 -sticky w
346  grid $w.o.indentc -row 3 -column 0 -sticky w
347  grid $w.o.vars -row 4 -column 0 -sticky w
348  grid $w.o.indentv -row 5 -column 0 -sticky w
349  grid $w.o.column -row 6 -column 0 -sticky w
350  grid $w.o.symbols -row 7 -column 0 -sticky w
351 
352  # Extra option for PGN format: handling of null moves
353  if {$exportType == "PGN"} {
354  ttk::checkbutton $w.o.nullMoves -variable exportFlags(convertNullMoves) -offvalue 0 -onvalue 1 -textvar ::tr(ConvertNullMove)
355  grid $w.o.nullMoves -row 8 -column 0 -sticky w
356  }
357 
358  # Extra option for HTML format: diagram image set
359  if {$exportType == "HTML"} {
360  ttk::label $w.o.hdiag -text "Diagram"
361  ttk::radiobutton $w.o.hb0 -text "bitmaps" \
362  -variable exportFlags(htmldiag) -value 0
363  ttk::radiobutton $w.o.hb1 -text "bitmaps2" \
364  -variable exportFlags(htmldiag) -value 1
365  ttk::label $w.o.hl0 -image htmldiag0
366  ttk::label $w.o.hl1 -image htmldiag1
367  grid $w.o.hdiag -row 8 -column 0 -sticky w
368  grid $w.o.hb0 -row 9 -column 0 -sticky w
369  grid $w.o.hb1 -row 9 -column 1 -sticky w
370  grid $w.o.hl0 -row 10 -column 0 -sticky w
371  grid $w.o.hl1 -row 10 -column 1 -sticky w
372  }
373 
374  pack [ttk::frame $w.b] -side top -fill x
375  dialogbutton $w.b.ok -text "OK" -command {
376  set exportFlags(ok) 1
377  }
378  dialogbutton $w.b.cancel -text $::tr(Cancel) -command {
379  set exportFlags(ok) 0
380  }
381  packbuttons right $w.b.cancel $w.b.ok
382 
383  wm withdraw $w
384  update idletasks
385  set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
386  - [winfo vrootx [winfo parent $w]]}]
387  set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
388  - [winfo vrooty [winfo parent $w]]}]
389  wm geom $w +$x+$y
390  wm deiconify $w
391 
392  grab $w
393  tkwait variable exportFlags(ok)
394  grab release $w
395  destroy $w
396  return $exportFlags(ok)
397 }
398 
399 # exportGames:
400 # exports current game or all filtered games to a new PGN, LaTeX or Html file.
401 #
402 proc exportGames {selection exportType} {
403  global ::pgn::moveNumberSpaces exportStartFile exportEndFile exportFlags
404  if {$selection == "filter" && [sc_filter count] == 0} {
405  tk_messageBox -title "Scid: Filter empty" -type ok -icon info \
406  -message "The filter contains no games."
407  return
408  }
409 
410  if {[exportOptions $exportType] == 0} { return}
411  sc_info html $exportFlags(htmldiag)
412 
413  switch -- $exportType {
414  "PGN" {
415  set ftype {
416  { "PGN files" {".pgn"} }
417  { "All files" {"*"} }
418  }
419  set title "a PGN file"
420  set idir $::initialDir(base)
421  set default ".pgn"
422  }
423  "HTML" {
424  set ftype {
425  { "HTML files" {".html" ".htm"} }
426  { "All files" {"*"} }
427  }
428  set title "an HTML file"
429  set idir $::initialDir(html)
430  set default ".html"
431  }
432  "LaTeX" {
433  set ftype {
434  { "LaTeX files" {".tex" ".ltx"} }
435  { "All files" {"*"} }
436  }
437  set title "a LaTeX file"
438  set idir $::initialDir(tex)
439  set default ".tex"
440  }
441  default { return}
442  }
443 
444  if {$exportFlags(append)} {
445  set getfile tk_getOpenFile
446  set title "Add games to $title"
447  } else {
448  set getfile tk_getSaveFile
449  set title "Create $title"
450  }
451  set fName [$getfile -initialdir $idir -filetypes $ftype -defaultextension $default -title $title]
452  if {$fName == ""} { return}
453 
454  progressWindow "Scid" "Exporting games..." $::tr(Cancel)
455  sc_base export $selection $exportType $fName -append $exportFlags(append) \
456  -starttext $exportStartFile($exportType) \
457  -endtext $exportEndFile($exportType) \
458  -comments $exportFlags(comments) -variations $exportFlags(vars) \
459  -space $::pgn::moveNumberSpaces -symbols $exportFlags(symbols) \
460  -indentC $exportFlags(indentc) -indentV $exportFlags(indentv) \
461  -column $exportFlags(column) -noMarkCodes $exportFlags(stripMarks) \
462  -convertNullMoves $exportFlags(convertNullMoves)
464 }
465 
466 ###########################################################################
467 ### Global variables used in gameSave:
468 set date 0; set year 0; set month 0; set day 0; set white 0; set black 0
469 set resultVal 0; set event 0; set site 0; set round 0
470 set whiteElo 0; set blackElo 0; set eco 0; set extraTags ""
471 set whiteRType "Elo"; set blackRType "Elo"
472 set edate 0; set eyear 0; set emonth 0; set eday 0
473 
474 # Traces on game-save dialog variables to ensure sane values:
475 
476 trace variable resultVal w ::utils::validate::Result
477 trace variable whiteElo w {::utils::validate::Integer [sc_info limit elo] 0}
478 trace variable blackElo w {::utils::validate::Integer [sc_info limit elo] 0}
479 trace variable year w {::utils::validate::Integer [sc_info limit year] 1}
480 trace variable month w {::utils::validate::Integer 12 1}
481 trace variable day w {::utils::validate::Integer 31 1}
482 trace variable eyear w {::utils::validate::Integer [sc_info limit year] 1}
483 trace variable emonth w {::utils::validate::Integer 12 1}
484 trace variable eday w {::utils::validate::Integer 31 1}
485 
486 set gsaveNum 0
487 set i 0; set j 0
488 set temp 0
489 
490 array set nameMatches {}
491 set nameMatchCount 0
492 
493 # updateMatchList:
494 # Called from gameSave to update the matching name list as the user
495 # types a player/site/event/round name.
496 #
497 proc updateMatchList { tw nametype maxMatches name el op } {
498  global nameMatches nameMatchCount
499  global $name editNameType
500  if {![winfo exists $tw]} return
501 
502  if {$nametype == ""} { set nametype $editNameType}
503  if {$nametype == "rating"} { set nametype "player"}
504  set val [set $name]
505  $tw configure -state normal
506  $tw delete 0.0 end
507  set matches {}
508  catch {set matches [sc_name match $nametype $val $maxMatches]}
509  set count [llength $matches]
510  set nameMatchCount [expr {$count / 2}]
511  for {set i 0} { $i < $count } {incr i 2} {
512  set nameMatchCount [expr {($i / 2) + 1}]
513  set nameMatches($nameMatchCount) [lindex $matches [expr {$i + 1}]]
514  set str "$nameMatchCount:\t[lindex $matches $i]\t$nameMatches($nameMatchCount)\n"
515  $tw insert end $str
516  }
517  $tw configure -state disabled
518 }
519 
520 proc clearMatchList { tw } {
521  global nameMatches nameMatchCount
522  set nameMatchCount 0
523  $tw configure -state normal
524  $tw delete 0.0 end
525  $tw configure -state disabled
526 }
527 
528 # Traces to update the match list as names are typed in:
529 
530 trace variable event w { updateMatchList .save.g.list e 9 }
531 trace variable site w { updateMatchList .save.g.list s 9 }
532 trace variable white w { updateMatchList .save.g.list p 9 }
533 trace variable black w { updateMatchList .save.g.list p 9 }
534 trace variable round w { updateMatchList .save.g.list r 9 }
535 
536 set editName ""
537 set editNameNew ""
538 set editNameType "player"
539 set editNameSelect "all"
540 set editNameRating ""
541 set editNameRType "Elo"
542 set editDate ""
543 set editDateNew ""
544 
545 trace variable editNameRating w {::utils::validate::Integer [sc_info limit elo] 0}
546 trace variable editName w { updateMatchList .nedit.g.list "" 9 }
547 trace variable editDate w ::utils::validate::Date
548 trace variable editDateNew w ::utils::validate::Date
549 
550 proc editNameNewProc { tw nametype maxMatches name el op } {
551  global editNameNew
552  if {! [winfo exists .nedit]} { return}
553  if {[string compare $editNameNew ""]} {
554  .nedit.buttons.replace configure -state normal
555  } else {
556  .nedit.buttons.replace configure -state disabled
557  }
558  catch {updateMatchList $tw $nametype $maxMatches $name $el $op}
559 }
560 
561 trace variable editNameNew w { editNameNewProc .nedit.g.list "" 9 }
562 
563 
564 set nameEditorWin 0
565 
566 proc makeNameEditor {} {
567  if {! [winfo exists .nedit]} { nameEditor}
568 }
569 
570 proc setNameEditorType {type} {
571  if {! [winfo exists .nedit]} { return}
572  catch {.nedit.typeButtons.$type invoke}
573 }
574 
575 proc nameEditor {} {
576  global editName editNameType editNameNew nameEditorWin editNameSelect
577  global editNameRating editDate editDateNew
578 
579  set w .nedit
580  if {[winfo exists $w]} {
581  destroy $w
582  return
583  }
585  wm title $w "Scid: [tr FileMaintNameEditor]"
586  set nameEditorWin 1
587  setWinLocation $w
588  bind $w <Configure> "recordWinSize $w"
589 
590  ttk::labelframe $w.typeButtons -text $::tr(NameEditType)
591  pack $w.typeButtons -side top -fill x -anchor w
592  foreach i { "Player" "Event" "Site" "Round"} col {0 1 2 3} {
593  set j [string tolower $i]
594  ttk::radiobutton $w.typeButtons.$j -textvar ::tr($i) -variable editNameType \
595  -value $j -command {
596  grid remove .nedit.g.ratingE
597  grid remove .nedit.g.rtype
598  grid remove .nedit.g.fromD
599  grid remove .nedit.g.toD
600  grid .nedit.g.toL -row 1 -column 1 -sticky e
601  grid .nedit.g.fromE -row 0 -column 2 -sticky w
602  grid .nedit.g.toE -row 1 -column 2 -sticky w
603  }
604  grid $w.typeButtons.$j -row 1 -column $col -sticky w -padx "0 5"
605  }
606  ttk::radiobutton $w.typeButtons.rating -textvar ::tr(Rating) -variable editNameType \
607  -value rating -command {
608  grid remove .nedit.g.toE
609  grid remove .nedit.g.toL
610  grid remove .nedit.g.fromD
611  grid remove .nedit.g.toD
612  grid .nedit.g.fromE -row 0 -column 2 -sticky w
613  grid .nedit.g.rtype -row 1 -column 0 -columnspan 2 -sticky e
614  grid .nedit.g.ratingE -row 1 -column 2 -sticky w
615  }
616  grid $w.typeButtons.rating -row 2 -column 0 -columnspan 2 -sticky w
617  ttk::radiobutton $w.typeButtons.date -textvar ::tr(Date) -variable editNameType \
618  -value date -command {
619  grid remove .nedit.g.toE
620  grid remove .nedit.g.fromE
621  grid remove .nedit.g.ratingE
622  grid remove .nedit.g.rtype
623  grid .nedit.g.fromD -row 0 -column 2 -sticky w
624  grid .nedit.g.toL -row 1 -column 1 -sticky e
625  grid .nedit.g.toD -row 1 -column 2 -sticky w
626  }
627  grid $w.typeButtons.date -row 2 -column 1 -sticky w -padx "0 5"
628  ttk::radiobutton $w.typeButtons.edate -textvar ::tr(EventDate) \
629  -variable editNameType -value edate \
630  -command {
631  grid remove .nedit.g.toE
632  grid remove .nedit.g.fromE
633  grid remove .nedit.g.ratingE
634  grid remove .nedit.g.rtype
635  grid .nedit.g.fromD -row 0 -column 2 -sticky w
636  grid .nedit.g.toL -row 1 -column 1 -sticky e
637  grid .nedit.g.toD -row 1 -column 2 -sticky w
638  }
639  grid $w.typeButtons.edate -row 2 -column 2 -sticky w -columnspan 2
640 
641  ttk::labelframe $w.selectButtons -text $::tr(NameEditSelect)
642  pack $w.selectButtons -side top -fill x -pady 10
643  foreach i {all filter crosstable} row {0 1 2} text {
644  SelectAllGames
645  SelectFilterGames
646  SelectTournamentGames
647  } {
648  ttk::radiobutton $w.selectButtons.$i -textvar ::tr($text) \
649  -variable editNameSelect -value $i
650  grid $w.selectButtons.$i -row $row -column 0 -sticky w
651  }
652 
653  pack [ttk::frame $w.g] -side top -fill x
654  ttk::label $w.g.fromL -textvar ::tr(NameEditReplace:) -font font_Bold -anchor e
655  ttk::entry $w.g.fromE -width 40 -textvariable editName
656  ttk::entry $w.g.fromD -width 15 -textvariable editDate
657  grid $w.g.fromL -row 0 -column 1 -sticky e
658  grid $w.g.fromE -row 0 -column 2 -sticky we
659 
660  ttk::label $w.g.toL -textvar ::tr(NameEditWith:) -font font_Bold -anchor e
661  ttk::entry $w.g.toE -width 40 -textvariable editNameNew
662  ttk::entry $w.g.toD -width 15 -textvariable editDateNew
663  grid $w.g.toL -row 1 -column 1 -sticky e
664  grid $w.g.toE -row 1 -column 2 -sticky we
665 
666  ttk::entry $w.g.ratingE -width 5 -textvariable editNameRating -justify right
667  set mlist [split [sc_info ratings] " "]
668  ttk::menubutton $w.g.rtype -textvariable editNameRType -menu $w.g.rtype.menu
669  menu $w.g.rtype.menu
670  foreach m $mlist {
671  $w.g.rtype.menu add radiobutton -variable editNameRType -label $m
672  }
673 
674  ttk::label $w.g.title -textvar ::tr(NameEditMatches) \
675  -font font_Bold
676  text $w.g.list -height 9 -width 40 -relief sunken \
677  -background grey90 -tabs {2c right 2.5c left} -wrap none
678 
679  grid $w.g.title -row 2 -column 1 -columnspan 2 -sticky n
680  grid $w.g.list -row 3 -column 1 -rowspan 9 -columnspan 2 -sticky e
681 
682  updateMatchList $w.g.list "" 9 editName "" w
683 
684  foreach i {fromE toE ratingE fromD toD} {
685  bind $w.g.$i <FocusIn> { %W configure -background lightYellow }
686  bind $w.g.$i <FocusOut> { %W configure -background white }
687  }
688  foreach {i j} {.nedit.g.fromE "editName" .nedit.g.toE "editNameNew" } {
689  for {set z 1} {$z <= 9} {incr z} {
690  bind $i [format "<Control-Key-%d>" $z] \
691  [format "eval {if {\$nameMatchCount >= %d} { \
692  set %s \$nameMatches(%d)}}; break" $z $j $z]
693  }
694  }
695 
696  ttk::frame $w.buttons
697  ttk::button $w.buttons.replace -textvar ::tr(NameEditReplace) -command {
698  if {$editNameType == "rating"} {
699  set err [catch {sc_name edit $editNameType $editNameSelect $editName $editNameRating $editNameRType} result]
700  } elseif {$editNameType == "date" || $editNameType == "edate"} {
701  set err [catch {sc_name edit $editNameType $editNameSelect $editDate $editDateNew} result]
702  } else {
703  set err [catch {sc_name edit $editNameType $editNameSelect $editName $editNameNew} result]
704  }
705  if {$err} {
706  ERROR::MessageBox
707  } else {
708  .nedit.status configure -text "Modified $result games."
709  }
710  sc_game tags reload
711  updateBoard -pgn
712  ::windows::gamelist::Refresh
713  }
714 
715  dialogbutton $w.buttons.cancel -textvar ::tr(Close) -command {focus .; destroy .nedit}
716  pack $w.buttons -fill x
717  packdlgbuttons $w.buttons.cancel $w.buttons.replace
718 
719  ttk::label $w.status -text "" -width 1 -font font_Small -relief sunken -anchor w
720  pack $w.status -side bottom -fill x
721 
722  wm resizable $w 0 0
723  bind $w <Escape> { focus .; destroy .nedit }
724  bind $w <Return> {.nedit.buttons.replace invoke}
725  bind $w <Destroy> {set nameEditorWin 0}
726  bind $w <F1> {helpWindow Maintenance Editing}
727  focus $w
728  $w.typeButtons.$editNameType invoke
729 }
730 
731 
732 # addGameSaveEntry:
733 # used in gameSave for setting up the simpler labels and entry boxes.
734 #
735 proc addGameSaveEntry { name row textname } {
736  ttk::label .save.g.label$name -textvar $textname
737  ttk::entry .save.g.entry$name -width 30 -textvariable $name
738  grid .save.g.label$name -row $row -column 0 -sticky w
739  grid .save.g.entry$name -row $row -column 1 -columnspan 7 -sticky w
740 }
741 
742 # gameSave:
743 # The game save dialog. Used for adding and replacing games. If the
744 # value gnum is zero, it is to add a new game; otherwise it is to
745 # replace game number gnum.
746 #
747 proc gameSave { gnum } {
748  global date year month day white black resultVal event site round
749  global whiteElo blackElo whiteRType blackRType eco extraTags gsaveNum
750  global edate eyear emonth eday
751 
752  # Make a new toplevel that contains the game save dialog:
753  set w .save
754  if {[winfo exists $w]} { return}
756  if {$gnum == 0} {
757  wm title $w "Scid: [tr GameAdd]"
758  pack [ttk::frame $w.refdb] -side top -fill x -pady {0 10}
759  CreateSelectDBWidget "$w.refdb" "gameSave_toBase" [sc_base current] 0
760  } else {
761  wm title $w "Scid: [tr GameReplace]"
762  }
763  set gsaveNum $gnum
764  catch {grab $w}
765 
766  set f [ttk::frame $w.g]
767  pack $f -side top -anchor w
768 
769  ttk::label $f.title -textvar ::tr(NameEditMatches)
770  text $f.list -height 9 -width 40 -relief sunken -background grey90 \
771  -tabs {2c right 2.5c left} -wrap none
772 
773  # Get current values of tags:
774  set year [sc_game tag get Year]; set eyear [sc_game tag get EYear]
775  set month [sc_game tag get Month]; set emonth [sc_game tag get EMonth]
776  set day [sc_game tag get Day]; set eday [sc_game tag get EDay]
777  set white [sc_game tag get White]; set black [sc_game tag get Black]
778  set event [sc_game tag get Event]; set site [sc_game tag get Site]
779  set resultVal [sc_game tag get Result]; set round [sc_game tag get Round]
780  set whiteElo [sc_game tag get WhiteElo]
781  set blackElo [sc_game tag get BlackElo]
782  set whiteRType [sc_game tag get WhiteRType]
783  set blackRType [sc_game tag get BlackRType]
784  set eco [sc_game tag get ECO]
785  set extraTags [sc_game tag get Extra]
786  if {[::board::isFlipped .main.board]} {
787  regsub -all {FlipB "[01]"\n} $extraTags {} extraTags
788  append extraTags "FlipB \"1\"\n"
789  } else {
790  regexp {FlipB "([01])"\n} $extraTags -> flipB
791  if {[info exists flipB] && $flipB} {
792  regsub -all {FlipB "[01]"\n} $extraTags {} extraTags
793  }
794  }
795  clearMatchList $f.list
796 
797  # Use question marks instead of zero values in date:
798  if {$year == 0} { set year "????"}
799  if {$month == 0} { set month "??"}
800  if {$day == 0} { set day "??"}
801  if {$eyear == 0} { set eyear "????"}
802  if {$emonth == 0} { set emonth "??"}
803  if {$eday == 0} { set eday "??"}
804 
805  addGameSaveEntry event 0 ::tr(Event:)
806  addGameSaveEntry site 1 ::tr(Site:)
807 
808  ttk::frame $f.dateframe
809  ttk::label $f.datelabel -textvar ::tr(Date:)
810  ttk::entry $f.dateyear -width 6 -textvariable year -justify right ;# -background white -relief sunken
811  ttk::label $f.datedot1 -text "."
812  ttk::entry $f.datemonth -width 3 -textvariable month -justify right
813  ttk::label $f.datedot2 -text "."
814  ttk::entry $f.dateday -width 3 -textvariable day -justify right
815  grid $f.datelabel -row 2 -column 0 -sticky w
816  grid $f.dateframe -row 2 -column 1 -columnspan 5 -sticky w
817  ttk::button $f.datechoose -image tb_calendar -style Pad0.Small.TButton -command {
818  set newdate [::utils::date::chooser "$year-$month-$day"]
819  if {[llength $newdate] == 3} {
820  set year [lindex $newdate 0]
821  set month [lindex $newdate 1]
822  set day [lindex $newdate 2]
823  }
824  }
825  ttk::button $f.today -textvar ::tr(Today) -command {
826  set year [::utils::date::today year]
827  set month [::utils::date::today month]
828  set day [::utils::date::today day]
829  }
830  pack $f.dateyear $f.datedot1 $f.datemonth $f.datedot2 $f.dateday \
831  -in $f.dateframe -side left
832  if {$::tcl_version >= 8.3} {
833  pack $f.datechoose -in $f.dateframe -side left
834  }
835  pack $f.today -in $f.dateframe -side left
836 
837  ttk::frame $f.edateframe
838  ttk::label $f.edatelabel -textvar ::tr(EventDate:)
839  ttk::entry $f.edateyear -width 6 -textvariable eyear -justify right
840  ttk::label $f.edatedot1 -text "."
841  ttk::entry $f.edatemonth -width 3 -textvariable emonth -justify right
842  ttk::label $f.edatedot2 -text "."
843  ttk::entry $f.edateday -width 3 -textvariable eday -justify right
844  grid $f.edatelabel -row 3 -column 0 -sticky w
845  grid $f.edateframe -row 3 -column 1 -columnspan 5 -sticky w
846  ttk::button $f.edatechoose -image tb_calendar -style Pad0.Small.TButton -command {
847  set newdate [::utils::date::chooser "$eyear-$emonth-$eday"]
848  if {[llength $newdate] == 3} {
849  set eyear [lindex $newdate 0]
850  set emonth [lindex $newdate 1]
851  set eday [lindex $newdate 2]
852  }
853  }
854  ttk::button $f.esame -text "=$::tr(Date)" -command {
855  set eyear $year
856  set emonth $month
857  set eday $day
858  }
859  pack $f.edateyear $f.edatedot1 $f.edatemonth $f.edatedot2 $f.edateday \
860  -in $f.edateframe -side left
861  if {$::tcl_version >= 8.3} {
862  pack $f.edatechoose -in $f.edateframe -side left
863  }
864  pack $f.esame -in $f.edateframe -side left
865 
866  addGameSaveEntry round 4 ::tr(Round:)
867  addGameSaveEntry white 5 ::tr(White:)
868  addGameSaveEntry black 6 ::tr(Black:)
869 
870  ttk::label $f.reslabel -textvar ::tr(Result:)
871  ttk::frame $f.resentry
872  ttk::radiobutton $f.resentry.w -text "1-0 " -variable resultVal -value 1
873  ttk::radiobutton $f.resentry.b -text "0-1 " -variable resultVal -value 0
874  ttk::radiobutton $f.resentry.r -text "1/2-1/2 " -variable resultVal -value =
875  ttk::radiobutton $f.resentry.u -text "*" -variable resultVal -value *
876  pack $f.resentry.w $f.resentry.b $f.resentry.r $f.resentry.u -side left
877  grid $f.reslabel -row 7 -column 0 -sticky w
878  grid $f.resentry -row 7 -column 1 -sticky w -columnspan 4
879 
880  ttk::label $f.welolabel -text "$::tr(White) "
881 
882  ttk::combobox $f.wrtype -values [sc_info ratings] -width 7 -textvariable whiteRType
883 
884  ttk::entry $f.weloentry -width 5 -textvariable whiteElo -justify right
885 
886  ttk::label $f.belolabel -text "$::tr(Black) "
887 
888  ttk::combobox $f.brtype -values [sc_info ratings] -width 7 -textvariable blackRType
889 
890  ttk::entry $f.beloentry -width 5 -textvariable blackElo -justify right
891 
892  grid $f.welolabel -row 8 -column 0 -sticky w
893  grid $f.wrtype -row 8 -column 1 -sticky w
894  grid $f.weloentry -row 8 -column 2 -sticky w
895  grid $f.belolabel -row 9 -column 0 -sticky w
896  grid $f.brtype -row 9 -column 1 -sticky w
897  grid $f.beloentry -row 9 -column 2 -sticky w
898 
899  ttk::label $f.ecolabel -text "ECO Code:"
900  ttk::entry $f.ecoentry -width 6 -textvariable eco
901  grid $f.ecolabel -row 10 -column 0 -sticky w
902  grid $f.ecoentry -row 10 -column 1 -sticky w
903 
904  ttk::button $f.ecob -textvar ::tr(ClassifyGame) -command {set eco [sc_eco game]}
905  grid $f.ecob -row 10 -column 2 -sticky w
906 
907  grid $f.title -row 0 -column 8 -sticky w -padx "10 0"
908  grid $f.list -row 1 -column 8 -rowspan 9 -sticky nw -padx "10 0"
909 
910  ttk::labelframe .save.extra -text "Extra Tags: (example format: Annotator \"Anand, V\") "
911  pack .save.extra -side top -fill both -expand 1
912  text .save.extra.text -height 4 -width 40 -bg white -wrap none \
913  -yscrollcommand ".save.extra.scroll set"
914  # Override tab-binding for this text widget:
915  bind .save.extra.text <Key-Tab> "[bind all <Key-Tab>]; break"
916  ttk::scrollbar .save.extra.scroll -command ".save.extra.text yview" -takefocus 0
917  ttk::button .save.extra.last -text $::tr(UseLastTag) -command {
918  set extraTags [sc_game tag get -last Extra]
919  .save.extra.text delete 1.0 end
920  .save.extra.text insert 1.0 $extraTags
921  }
922  pack .save.extra.text -side left -fill both -expand 1
923  if {$gnum == 0} {
924  pack .save.extra.last -side right -padx 10
925  }
926  pack .save.extra.scroll -side right -fill y
927  .save.extra.text insert 1.0 $extraTags
928 
929  foreach i {entryevent entrysite dateyear datemonth dateday \
930  entryround entrywhite entryblack resentry \
931  weloentry beloentry ecoentry edateyear edatemonth edateday} {
932  bind $f.$i <Return> {.save.buttons.save invoke}
933  # bind $f.$i <FocusIn> {%W configure -background lightYellow }
934  # bind $f.$i <FocusOut> {%W configure -background white }
935  }
936  bind .save.extra.text <FocusIn> {%W configure -background lightYellow }
937  bind .save.extra.text <FocusOut> {%W configure -background white }
938 
939  # Bindings so Ctrl-1 to Ctrl-9 select a matching name in the player,
940  # site, event and round entryboxes:
941 
942  set j 0
943  foreach {i j} {entryevent "event" entrysite "site"
944  entrywhite "white" entryblack "black"
945  entryround "round" } {
946  for {set z 1} {$z <= 9} {incr z} {
947  bind $f.$i [format "<Control-Key-%d>" $z] \
948  [format "eval {if {\$nameMatchCount >= %d} \
949  {set %s \$nameMatches(%d)}}" $z $j $z]
950  }
951  }
952 
953  ttk::frame .save.buttons
954  if {$gnum == 0} {
955  ttk::button .save.buttons.prev -text "As last game" -command {
956  }
957  }
958  dialogbutton .save.buttons.save -textvar ::tr(Save) -underline 0 -command {
959  set extraTags [.save.extra.text get 1.0 end-1c]
960  if { [gsave $gsaveNum] } {
961  destroy .save
962  } else {
963  ERROR::MessageBox
964  }
965  }
966  # bind .save <Alt-s> { .save.buttons.save invoke; break }
967 
968  dialogbutton .save.buttons.cancel -textvar ::tr(Cancel) -command {destroy .save}
969  pack .save.buttons -side bottom -padx 10 -fill both -expand 1
970  if {$gnum == 0} {
971  #pack .save.buttons.prev -side left -padx 10
972  }
973  packdlgbuttons .save.buttons.cancel .save.buttons.save
974 
975  bind .save <Escape> { focus .; destroy .save; }
977  focus .save.g.entryevent
978  .save.g.entryevent selection range 0 end
979  if {$gnum > 0} { focus .save.buttons.save}
980 }
981 
982 # gsave:
983 # Called by gameSave when the user presses the "Save" button
984 # to save the game. Attempts to save and reports the result.
985 #
986 proc gsave { gnum } {
987  global date year month day white black resultVal event site round
988  global whiteElo blackElo whiteRType blackRType eco extraTags
989  global edate eyear emonth eday
990 
991  set date [format "%s.%s.%s" $year $month $day]
992  set edate [format "%s.%s.%s" $eyear $emonth $eday]
993  set extraTagsList [split $extraTags "\n"]
994  sc_game tags set -event $event -site $site -date $date -round $round \
995  -white $white -black $black -result $resultVal \
996  -whiteElo $whiteElo -whiteRatingType $whiteRType \
997  -blackElo $blackElo -blackRatingType $blackRType \
998  -eco $eco -eventdate $edate -extra $extraTagsList
999  if {$gnum != 0} {
1000  if { [catch {sc_game save $gnum}] } { return 0}
1003  } else {
1004  set ply [sc_pos pgnOffset]
1005  if { [catch {sc_game save $gnum $::gameSave_toBase}] } { return 0}
1006  ::notify::DatabaseModified $::gameSave_toBase
1007  ::file::SwitchToBase $::gameSave_toBase 0
1008  ::game::Load [sc_base numGames $::gameSave_toBase]
1009  ::move::PGNOffset $ply
1010  }
1011  return 1
1012 }
1013 
1014 # gameAdd:
1015 # Calls gameSave with a game number of zero.
1016 #
1017 proc gameAdd {} { gameSave 0}
1018 
1019 proc gameAddToClipbase {} {
1020  if {[catch {sc_game save 0 $::clipbase_db}]} {
1022  }
1023  ::notify::DatabaseModified $::clipbase_db
1024 }
1025 
1026 # gameReplace:
1027 # Calls gameSave with the current game number, which should be nonzero.
1028 #
1029 proc gameReplace {} { gameSave [sc_game number]}
1030 
1031 
1032 # helpAbout:
1033 # Displays information about Scid.
1034 #
1035 proc helpAbout {} {
1036  ::utils::sound::PlaySound sound_move
1037  set str {}
1038  append str "Scid: Shane's chess information database\n\n"
1039  append str "Version $::scidVersion, $::scidVersionDate\n"
1040  append str "Copyright (C) 1999-2004 Shane Hudson\n"
1041  append str "Copyright (C) 2006-2009 Pascal Georges\n"
1042  append str "Copyright (C) 2008-2011 Alexander Wagner\n"
1043  append str "Copyright (C) 2011 Gerd Lorscheid\n"
1044  append str "Copyright (C) 2009-2019 Fulvio Benini\n"
1045  append str "\nScid is licenced under the\n"
1046  append str "GNU General Public License.\n"
1047 
1048  append str "\n\nUsing Tcl/Tk version: [info patchlevel]\n"
1049  append str "Loaded packages:\n"
1050  foreach {pkg} [lsort [package names]] {
1051  set ver [package provide $pkg]
1052  if {$ver != ""} { append str "$pkg\($ver), "}
1053  }
1054  regsub ", $" $str "." str
1055 
1056  tk_messageBox -title "About Scid" -message $str -type ok
1057 }
1058 
1059 
1060 proc MouseWheelRedirector {W X Y D} {
1061  # Generate an MWheel virtual event to the window that has the mouse pointer
1062  set w [winfo containing -displayof $W $X $Y]
1063  # Check for active "grab"
1064  set grabW [grab current $w]
1065  if {$grabW != ""} { set w $grabW}
1066  # For virtual events we can't use the attribute "-delta" and we get away
1067  # without a global variable by using instead "-data" which maps to %d
1068  event generate $w <<MWheel>> -data $D -rootx $X -rooty $Y
1069 }
1070 
1071 proc ShiftMouseWheelRedirector {W X Y D} {
1072  set w [winfo containing -displayof $W $X $Y]
1073  set grabW [grab current $w]
1074  if {$grabW != ""} { set w $grabW}
1075  event generate $w <<Shift-MWheel>> -data $D -rootx $X -rooty $Y
1076 }
1077 
1078 # On Windows, redirect mouse wheel events to those windows that have the
1079 # mouse pointer:
1080 # - Disable completely MouseWheel handling for all used classes. No class or
1081 # window should listen to MouseWheel to avoid double firing
1082 # - Any window that receives a MouseWheel redirects these events as MWheel
1083 # to the window with the mouse pointer
1084 # - Rebind all classes and windows that handle mouse wheel to MWheel events.
1085 # Bind code is from TCL 8.5
1086 # On Linux and Macs this redirection is not necessary
1087 
1088 if { [tk windowingsystem] == "win32" } {
1089  # Disable MouseWheel handling
1090  set mw_classes [list Text Listbox Treeview]
1091  foreach class $mw_classes { bind $class <MouseWheel> {}}
1092 
1093  # Transform MouseWheel events into MWheel
1094  bind all <MouseWheel> { MouseWheelRedirector %W %X %Y %D }
1095  bind all <Shift-MouseWheel> { ShiftMouseWheelRedirector %W %X %Y %D }
1096 
1097  # Bind classes to MWheel
1098  bind Listbox <<MWheel>> { %W yview scroll [expr {-(%d/120) * 4}] units}
1099  bind Treeview <<MWheel>> { %W yview scroll [expr {-(%d/120)}] units }
1100  bind Text <<MWheel>> {
1101  if {%d >= 0} { %W yview scroll [expr {-%d/3}] pixels
1102  } else { %W yview scroll [expr {(2-%d)/3}] pixels }
1103  }
1104 }
1105 
1106 
1107 #################
1108 # Open files and databases:
1109 
1110 # Check for arguments starting with "-" (or "/" on Windows):
1111 
1112 set loadAtStart(spell) 1
1113 set loadAtStart(eco) 1
1114 set loadAtStart(tb) 1
1115 
1116 proc getCommandLineOptions {} {
1117  global argc argv windowsOS loadAtStart
1118 
1119  if { $::macOS && ([string first "-psn" [lindex $argv 0]] == 0)} {
1120  # Remove Process Serial Number from argument list:
1121  set argv [lrange $argv 1 end]
1122  incr argc -1
1123  }
1124 
1125  while {$argc > 0} {
1126  set arg [lindex $argv 0]
1127  set firstChar [string index $arg 0]
1128  if {$firstChar == "-" || ($windowsOS && $firstChar == "/")} {
1129  # Seen option argument:
1130  incr argc -1
1131  set argv [lrange $argv 1 end]
1132 
1133  # Special argument "--" means no more options:
1134  if {$arg == "--"} { return}
1135 
1136  # Check for known option names:
1137  # -f (/f), -fast (/fast): Fast start with no tablebases, etc.
1138  # -xeco, -xe: Do not load ECO file.
1139  # -xspell, -xs: Do not load spellcheck file.
1140  # -xtb, -xt: Do not check tablebase directory.
1141 
1142  set argName [string range $arg 1 end]
1143  switch $argName {
1144  "f" -
1145  "fast" {
1146  ::splash::add "Fast start: no tablebases, ECO or spelling file loaded."
1147  set loadAtStart(spell) 0
1148  set loadAtStart(eco) 0
1149  set loadAtStart(tb) 0
1150  }
1151  "xt" -
1152  "xtb" {
1153  set loadAtStart(tb) 0
1154  }
1155  "xe" -
1156  "xeco" {
1157  set loadAtStart(eco) 0
1158  }
1159  "xs" -
1160  "xspell" {
1161  set loadAtStart(spell) 0
1162  }
1163  default {
1164  ::splash::add "Warning: unknown option: \"$arg\""
1165  }
1166  }
1167  } else {
1168  # Seen first non-option argument:
1169  return
1170  }
1171  }
1172 }
1173 
1175 
1176 # Try to find tablebases:
1177 if {$loadAtStart(tb)} {
1178  if {[sc_info tb]} {
1179  ::splash::add "Checking for endgame tablebase files..."
1180  set tbDirs {}
1181  foreach i {1 2 3 4} {
1182  if {$initialDir(tablebase$i) != ""} {
1183  if {$tbDirs != ""} { append tbDirs ";"}
1184  append tbDirs [file nativename $initialDir(tablebase$i)]
1185  }
1186  }
1187  set result 0
1188  if {$tbDirs != ""} {
1189  set result [sc_info tb $tbDirs]
1190  }
1191  if {$result == 0} {
1192  ::splash::add " No tablebases were found."
1193  } else {
1194  ::splash::add " Tablebases with up to $result pieces were found."
1195  }
1196  }
1197 }
1198 
1199 # Try to open the ECO classification file:
1200 set result 0
1201 set ecoFile_fullname [file nativename $ecoFile]
1202 
1203 if {$loadAtStart(eco)} {
1204  ::splash::add "Trying to load the ECO openings file..."
1205  if {[catch { sc_eco read $ecoFile_fullname} result]} {
1206  # Could not load, so try "scid.eco" in the current directory:
1207  if {[catch {sc_eco read "scid.eco"} result]} {
1208  # Neither attempt worked, so do not use ECO classification
1209  ::splash::add " Unable to open the ECO file: $ecoFile"
1210  } else {
1211  ::splash::add " ECO file \"./scid.eco\" loaded: $result positions."
1212  }
1213  } else {
1214  ::splash::add " ECO file \"[file tail $ecoFile_fullname]\" loaded: $result positions."
1215  }
1216 }
1217 
1218 ################################################################################
1219 # returns a list of all toplevel windows, except some that are utilities
1220 ################################################################################
1221 proc getTopLevel {} {
1222 
1223  set topl {}
1224  set exclude { ".glistExtra" ".menu" "." ".pgnPopup" }
1225  foreach c [winfo children .] {
1226  if { $c != [winfo toplevel $c] } { continue}
1227  # Tk report .__tk_filedialog as toplevel window even if the window has been closed
1228  if { [ lsearch $topl $c] == -1 && [ lsearch $exclude $c] == -1 && ![string match "\.__tk*" $c] } {
1229  lappend topl $c
1230  }
1231  }
1232  return $topl
1233 }
1234 ################################################################################
1235 #
1236 ################################################################################
1237 # showHideAllWindows:
1238 # Arranges for all major Scid windows to be shown/hidden
1239 # Should be called type = "iconify" or "deiconify"
1240 #
1241 proc showHideAllWindows {type} {
1242 
1243  # Don't do this if user option is off:
1244  if {! $::autoIconify} { return}
1245 
1246  # Some window managers like KDE generate Unmap events for other
1247  # situations like switching to another desktop, etc.
1248  # So if the main window is still mapped, do not iconify others:
1249  if {($type == "iconify") && ([winfo ismapped .main] == 1)} { return}
1250 
1251  # Now iconify/deiconify all the major Scid windows that exist:
1252  foreach w [getTopLevel] {
1253  if {[winfo exists $w]} { catch {wm $type $w}}
1254  }
1255 
1256 }
1257 
1258 proc raiseAllWindows {} {
1259  # Don't do this if auto-raise option is turned off:
1260  if {! $::autoRaise} { return}
1261 
1262  showHideAllWindows deiconify
1263 
1264  foreach w [getTopLevel] {
1265  if {[winfo exists $w]} { catch { raise $w}}
1266  }
1267 }
1268 
1269 # Disable ttk default left/right key bindings (they invoke ttk::notebook::CycleTab)
1270 bind TNotebook <Key-Right> {}
1271 bind TNotebook <Key-Left> {}
1272 
1273 wm iconname . "Scid"
1274 wm protocol . WM_DELETE_WINDOW { ::file::Exit }
1275 setMenu . .menu
1277 
1279 
1283 
1284 if {$startup(stats)} { ::windows::stats::Open}
1285 if {$startup(finder)} { ::file::finder::Open}
1286 if {$startup(tip)} { ::tip::show}
1287 
1288 # Try to load the spellcheck file:
1289 if {$loadAtStart(spell)} {
1290  progressWindow "Scid - [tr Spellcheking]" "Loading $spellCheckFile ..."
1291  set err [catch {sc_name read $spellCheckFile} result]
1293 }
1294 
1295 
1296 after 1 {
1297  ::file::autoLoadBases.load
1298 
1299  # fullname:
1300  # Given a file name, returns its absolute name.
1301  #
1302  proc fullname {fname} {
1303  if {[file pathtype $fname] == "absolute"} { return $fname }
1304  set old [pwd]
1305  if {[catch {cd [file dirname $fname]}]} { return $fname }
1306  set fname [file join [pwd] [file tail $fname]]
1307  catch {cd $old}
1308  return $fname
1309  }
1310  # Loading a database if specified on the command line:
1311  foreach cmdbase $::argv {
1312  ::file::Open "[fullname $cmdbase]"
1313  }
1314 }
1315 
1316 
1317 ### End of file: end.tcl