Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
start.tcl
Go to the documentation of this file.
1 #!/bin/sh
2 
3 # Scid (Shane's Chess Information Database)
4 #
5 # Copyright (C) 1999-2004 Shane Hudson
6 # Copyright (C) 2006-2009 Pascal Georges
7 # Copyright (C) 2008-2011 Alexander Wagner
8 # Copyright (C) 2013-2015 Fulvio Benini
9 #
10 # Scid is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation.
13 
14 #
15 # The following few comments are only for Unix versions of Scid:
16 #
17 
18 # The "\" at the end of the comment line below is necessary! It means
19 # that the "exec" line is a comment to Tcl/Tk, but not to /bin/sh.
20 # The next line restarts using tkscid: \
21 exec `dirname $0`/tkscid "$0" "$@"
22 # exec tkscid "$0" "$@"
23 
24 # The above launches tkscid from the same directory that this startup
25 # script was launched from (which feels as a suitable default scenario).
26 # Alternatively, you can change the top line of this startup script
27 # to start tkscid directly from a specific location, e.g.:
28 
29 # For the above to work, tkscid must be in a directory in your PATH.
30 # Alternatively, you can set the first line to start tkscid directly
31 # by specifying the full name of tkscid, eg:
32 # #!/home/myname/bin/tkscid
33 
34 ############################################################
35 
36 package require Tcl 8.5
37 package require Tk 8.5
38 if {$tcl_version == 8.5} { catch {package require img::png}}
39 
40 set scidVersion [sc_info version]
41 set scidVersionDate [sc_info version date]
42 set scidVersionExpected "4.7.0"
43 
44 # Check that the version of c++ code matches the version of tcl code
45 #
46 if {[string compare $::scidVersion $::scidVersionExpected]} {
47  wm withdraw .
48  set msg "This is Scid version $::scidVersion, but the scid GUI (tcl/tk code)\n"
49  append msg "has the version number $scidVersionExpected.\n"
50  tk_messageBox -type ok -icon error -title "Scid: Version Error" -message $msg
51  exit 1
52 }
53 
54 # Determine operating system platform: unix, windows or macos
55 #
56 set windowsOS 0
57 if {$tcl_platform(platform) == "windows"} { set windowsOS 1}
58 set unixOS 0
59 if {$tcl_platform(platform) == "unix"} { set unixOS 1}
60 set macOS 0
61 if {![catch {tk windowingsystem} wsystem] && $wsystem == "aqua"} { set macOS 1}
62 
63 proc InitDirs {} {
64  global scidExeDir scidUserDir scidConfigDir scidDataDir scidLogDir scidShareDir scidImgDir scidTclDir
65  global scidBooksDir scidBasesDir ecoFile
66 
67  # scidExeDir: contains the directory of the Scid executable program.
68  # Used to determine the location of various relative data directories.
69  set scidExecutable [info nameofexecutable]
70  if {[file type $scidExecutable] == "link"} {
71  set scidExeDir [file dirname [file readlink $scidExecutable]]
72  if {[file pathtype $scidExeDir] == "relative"} {
73  set scidExeDir [file dirname [file join [file dirname $scidExecutable]\
74  [file readlink $scidExecutable]]]
75  }
76  } else {
77  set scidExeDir [file dirname $scidExecutable]
78  }
79 
80  # scidUserDir: location of user-specific Scid files.
81  # This is "~/.scid" on Unix, and the Scid executable dir on Windows.
82  if {$::windowsOS} {
83  set scidUserDir $scidExeDir
84  } else {
85  regexp {(\d+\.\d+).*} $::scidVersion -> version
86  set scidUserDir [file nativename "~/.scid$version"]
87  }
88 
89  # scidConfigDir, scidDataDir, scidLogDir:
90  # Location of Scid configuration, data and log files.
91  set scidConfigDir [file nativename [file join $scidUserDir "config"]]
92  set scidDataDir [file nativename [file join $scidUserDir "data"]]
93  set scidLogDir [file nativename [file join $scidUserDir "log"]]
94 
95  # scidShareDir, scidImgDir, scidTclDir, scidBooksDir, scidBasesDir, ecoFile:
96  # Location of Scid resources
97  set scidShareDir [file normalize [file join $scidExeDir "../share/scid"]]
98  if {! [file isdirectory $::scidShareDir]} {
99  set scidShareDir $::scidExeDir
100  }
101  set scidTclDir [file nativename [file join $scidShareDir "tcl"]]
102  if {! [file isdirectory $scidTclDir]} {
103  set scidTclDir [file dirname [info script]]
104  set scidShareDir [file normalize "$scidTclDir/../"]
105  }
106  set scidImgDir [file nativename [file join $scidShareDir "img"]]
107 
108  #Default values, can be overwritten by file option
109  set scidBooksDir [file nativename [file join $scidShareDir "books"]]
110  set scidBasesDir [file nativename [file join $scidShareDir "bases"]]
111  set ecoFile [file nativename [file join $scidShareDir "scid.eco"]]
112 
113  proc moveOldConfigFiles {} {
114  # Moves configuration files from the old (3.4 and earlier) names
115  # to the new file names used since Scid 3.5.
116  global scidUserDir scidConfigDir
117 
118  # Since the options file used to be ".scid", rename it:
119  if {[file isfile $scidUserDir]} {
120  file rename -force $scidUserDir "$scidUserDir.old"
121  }
122 
123  # Rename old "~/.scid_sent_emails" if necessary:
124  if {[file isfile [file nativename "~/.scid_sent_emails"]]} {
125  catch {file rename [file nativename "~/.scid_sent_emails"] $email(logfile)}
126  }
127 
128  foreach {oldname newname} {
129  scidrc options.dat
130  scid.opt options.dat
131  scid.bkm bookmarks.dat
132  scid.rfl recentfiles.dat
133  engines.lis engines.dat
134  } {
135  set oldpath [file nativename [file join $scidUserDir $oldname]]
136  set newpath [file nativename [file join $scidConfigDir $newname]]
137  if {[file readable $oldpath] && ![file readable $newpath]} {
138  if {[catch {file rename $oldpath $newpath} err]} {
139  tk_messageBox -message "Error moving $oldpath to $newpath: $err"
140  }
141  }
142  }
143  }
145 
146  # Create the config, data and log directories if they do not exist:
147  proc makeScidDir {dir} {
148  if {! [file isdirectory $dir]} {
149  file mkdir $dir
150  }
151  }
152  makeScidDir $scidUserDir
153  makeScidDir $scidConfigDir
154  makeScidDir $scidDataDir
155  makeScidDir $scidLogDir
156 }
157 InitDirs
158 
159 #############################################################
160 #
161 # NAMESPACES
162 #
163 # The main Tcl/Tk namespaces used in the Scid application are
164 # initialized here, so that default values can be set up and
165 # altered when the user options file is loaded.
166 #
167 foreach ns {
168  ::splash
169  ::utils
170  ::utils::date ::utils::font ::utils::history ::utils::pane ::utils::string
171  ::utils::sound ::utils::validate ::utils::win
172  ::file
173  ::file::finder ::file::maint ::maint
174  ::bookmarks
175  ::edit
176  ::game
177  ::gbrowser
178  ::search
179  ::search::filter ::search::board ::search::header ::search::material
180  ::windows
181  ::windows::gamelist ::windows::stats ::tree ::tree::mask ::windows::tree
182  ::windows::switcher ::windows::eco ::crosstab ::pgn ::book
183  ::windows::commenteditor
184  ::tools
185  ::tools::analysis ::tools::email
186  ::tools::graphs
187  ::tools::graphs::filter ::tools::graphs::absfilter ::tools::graphs::rating ::tools::graphs::score
188  ::tb ::optable
189  ::board ::move
190  ::tacgame ::sergame ::opening ::tactics ::calvar ::uci ::fics ::reviewgame ::novag
191  ::config ::docking
192  ::pinfo
193  ::unsafe
194  ::utils::tooltip
195 } {
196  namespace eval $ns {}
197 }
198 
199 proc ::splash::add {text} {
200 #TODO: decide what to do with all the splash messages (delete?)
201 }
202 
203 # Platform specific operations
204 if { $unixOS } {
205  # adds a checkbox to show hidden files
206  catch {tk_getOpenFile -with-invalid-argument}
207  namespace eval ::tk::dialog::file {
208  variable showHiddenBtn 1
209  variable showHiddenVar 0
210  }
211 }
212 
213 # Reversed mouse buttons in mac (::MB2 and ::MB3 are middle and right mouse buttons respectively.):
214 if { $macOS } {
215  set ::MB2 3
216  set ::MB3 2
217 } else {
218  set ::MB2 2
219  set ::MB3 3
220 }
221 
222 
223 ####################################################
224 # safeSource() - source a file using a safe interpreter
225 # @filename: the absolute path to the file to source (load and execute)
226 # @args: pairs of varname value that are visible to the sourced code
227 #
228 # This function execute the code inside a safe tcl interpreter and override
229 # "set" to import the variables of the executed code in the ::unsafe namespace.
230 # Attention must be paid to not evaluate ::unsafe vars, for example:
231 # set ::unsafe::badcode {tk_messageBox -message executeme}
232 # eval $::unsafe::badcode
233 # after idle $::unsafe::badcode
234 
235 proc safeSource {filename args} {
236  if {![info exists ::safeInterp]} {
237  set ::safeInterp [::safe::interpCreate]
238  interp hide $::safeInterp set
239  interp alias $::safeInterp set {} ::safeSet $::safeInterp
240  }
241  set f [file nativename "$filename"]
242  set d [file dirname $f]
243  set n [file tail $f]
244  foreach {varname value} $args {
245  $::safeInterp eval [list set $varname $value]
246  }
247  $::safeInterp eval [list set vdir [::safe::interpAddToAccessPath $::safeInterp $d]]
248  $::safeInterp eval "source \$vdir/$n"
249  foreach {varname value} $args {
250  $::safeInterp eval [list unset $varname]
251  }
252 }
253 proc safeSet {i args} {
254  #TODO: do not import local variables
255  #if {[$::safeInterp eval info level] == 0}
256  foreach {varname value} $args {
257  set ::unsafe::$varname $value
258  }
259  interp invokehidden $i set {*}$args
260 }
261 
262 # Use a ::safe::interp to evaluate a file containing ttk::style and image commands.
263 # The evaluated script can only read the files inside its directory or direct subdirectories.
264 # @param filename: the absolute path to the file
265 
266 # recursiv identify all subdirs
267 proc safeAddSubDirsToAccessPath { safeInterp dir } {
268  foreach subdir [glob -nocomplain -directory $dir -type d *] {
269  ::safe::interpAddToAccessPath $safeInterp $subdir
270  safeAddSubDirsToAccessPath $safeInterp $subdir
271  }
272 }
273 
274 proc safeSourceStyle {filename} {
275  set filename [file nativename "$filename"]
276  set dir [file dirname $filename]
277 
278  set safeInterp [::safe::interpCreate]
279 
280  set vdir [::safe::interpAddToAccessPath $safeInterp $dir]
281  safeAddSubDirsToAccessPath $safeInterp $dir
282 
283  interp alias $safeInterp pwd {} ::safePwd
284  interp alias $safeInterp package {} ::safePackage $safeInterp
285  interp alias $safeInterp image {} ::safeImage $safeInterp [list $vdir $dir]
286  interp alias $safeInterp ttk::style {} ::safeStyle $safeInterp
287 
288  $safeInterp eval [list set vdir $vdir]
289  $safeInterp eval "source \$vdir/[file tail $filename]"
290  ::safe::interpDelete $safeInterp
291 }
292 
293 proc safePwd {} {}
294 
295 proc safePackage { interp args } {
296  set args [lassign $args command]
297  catch {
298  switch -- $command {
299  "require" { package require {*}$args}
300  "vsatisfies" { package vsatisfies {*}$args}
301  "provide" { package provide {*}$args}
302  }
303  }
304 }
305 
306 proc safeImage {interp dir_map args} {
307  set filename [lsearch -exact $args -file]
308  if {$filename != -1} {
309  incr filename
310  set real_filename [string map $dir_map [lindex $args $filename]]
311  set args [lreplace $args $filename $filename $real_filename]
312  }
313  return [image {*}$args]
314 }
315 
316 # Evaluate ttk::style commands invoked inside the restricted script.
317 # If the command includes a script (ttk::style theme settings or ttk::style theme create)
318 # it is evaluated using the safe interpreter.
319 proc safeStyle {interp args} {
320  lassign $args theme settings themeName script
321  if {$theme eq "theme"} {
322  if { $settings eq "settings"} {
323  set curr_theme [ttk::style theme use]
324  ttk::style theme use $themeName
325  $interp eval $script
326  ttk::style theme use $curr_theme
327  return
328  }
329 
330  set script_i [lsearch -exact $args -settings]
331  if {$script_i != -1} {
332  set script_j [expr $script_i + 1]
333  ttk::style {*}[lreplace $args $script_i $script_j]
334  $interp eval [list ttk::style theme settings $themeName [lindex $args $script_j]]
335  return
336  }
337  }
338 
339  return [ttk::style {*}$args]
340 }
341 
342 ####################################################
343 # Load default/saved values
344 source [file nativename [file join $::scidTclDir "options.tcl"]]
345 
346 
347 # Check for old (single-directory) tablebase option:
348 if {[info exists initialDir(tablebase)]} {
349  set initialDir(tablebase1) $initialDir(tablebase)
350 }
351 
352 proc createFonts {} {
353  foreach name {Regular Menu Small Tiny Fixed} {
354  set opts $::fontOptions($name)
355  font create font_$name \
356  -family [lindex $opts 0] -size [lindex $opts 1] \
357  -weight [lindex $opts 2] -slant [lindex $opts 3]
358  }
359 
360  set fontsize [font configure font_Regular -size]
361  set font [font configure font_Regular -family]
362  font create font_Bold -family $font -size $fontsize -weight bold
363  font create font_BoldItalic -family $font -size $fontsize -weight bold -slant italic
364  font create font_Italic -family $font -size $fontsize -slant italic
365  font create font_H1 -family $font -size [expr {$fontsize + 8}] -weight bold
366  font create font_H2 -family $font -size [expr {$fontsize + 6}] -weight bold
367  font create font_H3 -family $font -size [expr {$fontsize + 4}] -weight bold
368  font create font_H4 -family $font -size [expr {$fontsize + 2}] -weight bold
369  font create font_H5 -family $font -size [expr {$fontsize + 0}] -weight bold
370 
371  set fontsize [font configure font_Small -size]
372  set font [font configure font_Small -family]
373  font create font_SmallBold -family $font -size $fontsize -weight bold
374  font create font_SmallItalic -family $font -size $fontsize -slant italic
375 
376  set ::utils::tooltip::font font_Small
377 }
379 
380 # Load theme
381 if { [file exists $::ThemePackageFile] } {
382  catch { ::safeSourceStyle $::ThemePackageFile}
383 }
384 catch { ttk::style theme use $::lookTheme}
385 
386 #TODO: all the style configurations should be re-applied when the theme is changed
387 # Use default font everywhere
388 ttk::style configure TLabel -font font_Regular
389 ttk::style configure TButton -font font_Regular
390 ttk::style configure TRadiobutton -font font_Regular
391 ttk::style configure TCheckbutton -font font_Regular
392 ttk::style configure TMenubutton -font font_Regular
393 ttk::style configure TCombobox -font font_Regular
394 ttk::style configure TEntry -font font_Regular
395 ttk::style configure TNotebook.Tab -font font_Regular
396 
397 # Style definitions
398 ttk::style configure Bold.TCheckbutton -font font_Bold
399 ttk::style configure Small.TCheckbutton -font font_Small
400 
401 ttk::style configure Small.TButton -font font_Small
402 ttk::style configure Bold.TButton -font font_Bold
403 ttk::style configure Pad0.Small.TButton -padding 0
404 
405 ttk::style configure Small.TRadiobutton -font font_Small
406 ttk::style configure Bold.TRadiobutton -font font_Bold
407 ttk::style configure SmallBold.TRadiobutton -font font_SmallBold
408 
409 ttk::style configure pad0.TMenubutton -padding 0 -indicatorwidth 0 -indicatorheight 0 -font font_Small
410 
411 #TODO: recalculate the value if font_Small is changed
412 set ::glistRowHeight [expr { round(1.4 * [font metrics font_Small -linespace]) }]
413 ttk::style configure Gamelist.Treeview -rowheight $::glistRowHeight
414 
415 # font_Regular is the default font for widgets:
416 option add *Font font_Regular
417 
418 # Use font_Menu for menu entries:
419 option add *Menu*Font font_Menu
420 
421 # Use custom menu colors (if they exists)
422 foreach col [array names ::menuColor] {
423  option add *Menu.$col $::menuColor($col)
424 }
425 
426 # Apply the theme's background color to a widget
427 proc applyThemeColor_background { widget } {
428  set bgcolor [ttk::style lookup . -background "" #d9d9d9]
429  $widget configure -background $bgcolor
430  bind $widget <<ThemeChanged>> "::applyThemeColor_background $widget"
431 }
432 
433 # Apply a ttk style to a tk widget
434 proc applyThemeStyle {style widget} {
435  $widget configure -background [ttk::style lookup $style -background "" #d9d9d9]
436  $widget configure -foreground [ttk::style lookup $style -foreground "" black]
437  $widget configure -relief [ttk::style lookup $style -relief "" flat]
438  $widget configure {*}[ttk::style configure $style]
439  bind $widget <<ThemeChanged>> "::applyThemeStyle $style $widget"
440 }
441 
442 proc InitImg {} {
443  global scidImgDir boardStyle boardStyles textureSquare
444 
445  #Set app icon
446  set scidIconFile [file nativename [file join $scidImgDir "scid.gif"]]
447  if {[file readable $scidIconFile]} {
448  wm iconphoto . -default [image create photo -file "$scidIconFile"]
449  }
450 
451  #Load all img/buttons/_filename_.gif
452  set dname [file join $::scidImgDir buttons]
453  foreach {fname} [glob -directory $dname *.gif] {
454  set iname [string range [file tail $fname] 0 end-4]
455  image create photo $iname -file $fname
456  }
457 
458  #Load all img/buttons/_filename_.png
459  set dname [file join $::scidImgDir buttons]
460  foreach {fname} [glob -directory $dname *.png] {
461  set iname [string range [file tail $fname] 0 end-4]
462  image create photo $iname -format png -file $fname
463  }
464 
465  #Load all img/boards/_filename_.gif
466  set textureSquare {}
467  set dname [file join $::scidImgDir boards]
468  foreach {fname} [glob -directory $dname *.gif] {
469  set iname [string range [file tail $fname] 0 end-4]
470  image create photo $iname -file $fname
471  if {[string range $iname end-1 end] == "-l"} {
472  lappend textureSquare [string range $iname 0 end-2]
473  }
474  }
475 
476  #Search available piece sets
477  set boardStyles {}
478  set dname [file join $::scidImgDir pieces]
479  foreach {piecetype} [glob -directory $dname *] {
480  if {[file isdirectory $piecetype] == 1} {
481  lappend boardStyles [file tail $piecetype]
482  }
483  }
484 
485  #Load all img/flags/_filename_.gif
486  set dname [file join $::scidImgDir flags]
487  foreach {fname} [glob -directory $dname *.gif] {
488  set iname [string range [file tail $fname] 0 end-4]
489  image create photo $iname -file $fname
490  }
491 }
492 if {[catch {InitImg}]} {
493  tk_messageBox -type ok -icon error -title "Scid: Error" \
494  -message "Cannot load images.\n$::errorCode\n\n$::errorInfo"
495  exit
496 }
497 
498 # Set numeric format
499 sc_info decimal $::locale(numeric)
500 
501 # Start in the clipbase, if no database is loaded at startup.
502 set ::clipbase_db [sc_info clipbase]
503 sc_base switch $::clipbase_db
504 set ::curr_db [sc_base current]
505 
506 
507 set tcl_files {
508 language.tcl
509 errors.tcl
510 utils.tcl
511 utils/date.tcl
512 utils/font.tcl
513 utils/graph.tcl
514 utils/history.tcl
515 utils/pane.tcl
516 utils/sound.tcl
517 utils/string.tcl
518 utils/tooltip.tcl
519 utils/validate.tcl
520 utils/win.tcl
521 misc.tcl
522 htext.tcl
523 file.tcl
524 file/finder.tcl
525 file/bookmark.tcl
526 file/recent.tcl
527 file/spellchk.tcl
528 file/maint.tcl
529 edit.tcl
530 game.tcl
531 windows.tcl
532 windows/browser.tcl
533 windows/gamelist.tcl
534 windows/pgn.tcl
535 windows/book.tcl
536 windows/comment.tcl
537 windows/eco.tcl
538 windows/stats.tcl
539 windows/tree.tcl
540 windows/crosstab.tcl
541 windows/pfinder.tcl
542 windows/tourney.tcl
543 windows/switcher.tcl
544 search/search.tcl
545 search/board.tcl
546 search/header.tcl
547 search/material.tcl
548 contrib/ezsmtp/ezsmtp.tcl
549 tools/email.tcl
550 tools/import.tcl
551 tools/optable.tcl
552 tools/preport.tcl
553 tools/pinfo.tcl
554 tools/analysis.tcl
555 tools/wbdetect.tcl
556 tools/graphs.tcl
557 tools/tablebase.tcl
558 tools/ptracker.tcl
559 help/help.tcl
560 help/tips.tcl
561 appearance.tcl
562 keyboard.tcl
563 menus.tcl
564 board.tcl
565 move.tcl
566 main.tcl
567 tools/correspondence.tcl
568 tools/uci.tcl
569 end.tcl
570 tools/tacgame.tcl
571 tools/sergame.tcl
572 tools/calvar.tcl
573 tools/fics.tcl
574 tools/opening.tcl
575 tools/tactics.tcl
576 tools/reviewgame.tcl
577 utils/metadata.tcl
578 tools/inputengine.tcl
579 tools/novag.tcl
580 utils/bibliography.tcl
581 }
582 
583 foreach f $tcl_files {
584  source -encoding utf-8 [file nativename [file join $::scidTclDir "$f"]]
585 }
586 
587 ###
588 ### End of file: start.tcl