Attached my patch for this one.
This concludes the efficiency story as far as I would like to address
it.
I kept the limited-set-of-corrections [-max N] operational on the tkscid
API, with the convention that if N = 0, this is taken as "unlimited."
Both the spellchecker and the cleaner use this N = 0 value, thus finding
all corrections in one run.
Next I will address the spellchecker more from a qualitative perspective
E.g., ever seen a 1 year old playing a correspondence chess game? Scid
considers this most likely :-)
Happy hunting,
Joost.
On Mon, 2009-03-02 at 16:48 +0100, Joost ´t Hart wrote:
> Hi Pascal,
>
> I see I need just a little bit more patience :-)
>
> The switch - if defined, of course (!) - does exactly what it says: It
> makes scid bail out after it has found maxCorrections. This saves time.
>
> This means that it handles issue (2) from my previous posting.
>
> So, indeed my proposal is in line with your statement below, _PLUS_ /
> _BUT_
>
> I suggest NOT to use the maxCorrections option from the tcl layer at
> all.
> It is good to leave the C-code for this feature in there (we have it
> anyway), but I suggest not to use it, as it makes no sense (issue (1)).
>
> It seems this is the final thing we need to agree on. After this I am
> perfectly happy to resend a complete patch to be included in some
> release candidate.
>
> You can be sure that I (white-box-) tested a lot of different (dbase)
> use cases, but
> 1) developers should not be testers
> 2) I build and test only on Linux. I have a windoze XP PC as well, but
> no clue how to build for it
>
> So it is certainly better if someone else is willing to conduct some
> testing indeed.
>
> Cheers,
> Joost.
>
> On Mon, 2009-03-02 at 13:12 +0100, Pascal Georges wrote:
> > Thanks for your patience and your explanation. What I see :
> >
> > 1. The define is useless. I was mislead by your default
> > #undef BAIL_OUT_AFTER_MAXCORRECTIONS
> >
> > where
> >
> > #define BAIL_OUT_AFTER_MAXCORRECTIONS
> >
> > gives far better result, and I don't see much drawbacks using this one
> > (or did I miss something ?).
> >
> > So I agree with your conclusions (provided that you also think the
> > compiler switch should be the #define above) : could you post an
> > updated patch ?
> > Are there some users willing to test this ? My own tests are very
> > partial as, again, I am not a big user of name checking.
> >
> > Pascal
> > ------------------------------------------------------------------------------
> > Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
> > -OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
> > -Strategies to boost innovation and cut costs with open source participation
> > -Receive a $600 discount off the registration fee with the source code: SFAD
> > http://p.sf.net/sfu/XcvMzF8H
> > _______________________________________________ Scid-users mailing list
> > Scid-users@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/scid-users
? Makefile
? pgnfix
? pgnscid
? sc_addmove
? sc_eco
? sc_epgn
? sc_import
? sc_remote
? sc_spell
? sc_tree
? scid
? scid.log
? scidlet
? scidpgn
? scidt
? scmerge
? spf2spi
? spliteco
? tcscid
? tkscid
? engines/Phalanx-XXII/phalanx
? engines/togaII1.2.1a/src/.depend
? engines/togaII1.2.1a/src/fruit
Index: src/tkscid.cpp
===================================================================
RCS file: /cvsroot/scid/scid/src/tkscid.cpp,v
retrieving revision 1.29
diff -u -r1.29 tkscid.cpp
--- src/tkscid.cpp 10 Jan 2009 17:51:57 -0000 1.29
+++ src/tkscid.cpp 3 Mar 2009 18:38:20 -0000
@@ -10616,12 +10616,22 @@
idNumberT * newIDs = new idNumberT [nameCount];
dateT * startDate = new dateT [nameCount];
dateT * endDate = new dateT [nameCount];
-#endif
+#endif
+
+ bool interrupted = false;
+
+ // Set the scroll bar to its initial state
+ //
+ bool showProgress = startProgressBar();
+
+ // Scroll bar threshold (about 200 steps)
+ //
+ uint threshold = (db->numGames / 200) + 1;
for (idNumberT id=0; id < nameCount; id++) {
newIDs[id] = id;
- startDate[0] = ZERO_DATE;
- endDate[0] = ZERO_DATE;
+ startDate[id] = ZERO_DATE;
+ endDate[id] = ZERO_DATE;
}
while (*str != 0) {
@@ -10664,8 +10674,12 @@
if (correctionCount == 0) {
#ifdef WINCE
my_Tcl_Free((char*) newIDs);
+ my_Tcl_Free((char*) startDate);
+ my_Tcl_Free((char*) endDate);
#else
delete[] newIDs;
+ delete[] startDate;
+ delete[] endDate;
#endif
return setResult (ti, "No valid corrections were found.");
@@ -10675,8 +10689,12 @@
if ((!db->memoryOnly) && db->nb->WriteNameFile() != OK) {
#ifdef WINCE
my_Tcl_Free((char*) newIDs);
+ my_Tcl_Free((char*) startDate);
+ my_Tcl_Free((char*) endDate);
#else
delete[] newIDs;
+ delete[] startDate;
+ delete[] endDate;
#endif
return errorResult (ti, "Error writing name file.");
}
@@ -10757,19 +10775,48 @@
if (corrected) {
if (db->idx->WriteEntries (&newIE, i, 1) != OK) {
#ifdef WINCE
- my_Tcl_Free((char*) newIDs);
+ my_Tcl_Free((char*) newIDs);
+ my_Tcl_Free((char*) startDate);
+ my_Tcl_Free((char*) endDate);
#else
- delete[] newIDs;
-#endif
- return errorResult (ti, "Error writing index file.");
- }
- }
+ delete[] newIDs;
+ delete[] startDate;
+ delete[] endDate;
+#endif
+ return errorResult (ti, "Error writing index file.");
+ }
+ }
+
+ // Update the scroll bar
+ //
+ if ( showProgress && (i % threshold) == 1 ) {
+ updateProgressBar( ti, i, db->numGames );
+
+ // Give the user a chance for a safe interrupt
+ //
+ if ( (interrupted = interruptedProgress()) ) {
+ break;
+ }
+ }
+ }
+
+ if ( ! interrupted )
+ {
+ // Ensure the scroll bar is complete at this point
+ //
+ if ( showProgress ) {
+ updateProgressBar( ti, 1, 1 );
+ }
}
#ifdef WINCE
- my_Tcl_Free((char*) newIDs);
+ my_Tcl_Free((char*) newIDs);
+ my_Tcl_Free((char*) startDate);
+ my_Tcl_Free((char*) endDate);
#else
- delete[] newIDs;
+ delete[] newIDs;
+ delete[] startDate;
+ delete[] endDate;
#endif
if (db->idx->WriteHeader() != OK) {
@@ -12198,7 +12245,8 @@
*target = 0;
return;
}
-
+
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// sc_name_spellcheck:
// Scan the current database for spelling corrections.
@@ -12217,7 +12265,13 @@
};
enum {
OPT_MAX, OPT_SURNAMES, OPT_AMBIGUOUS
- };
+ };
+
+ bool interrupted = false;
+
+ // Set the progress bar to its intial state
+ //
+ bool showProgress = startProgressBar();
int arg = 2;
while (arg+1 < argc) {
@@ -12229,7 +12283,10 @@
switch (index) {
case OPT_MAX:
- maxCorrections = strGetUnsigned (value);
+ maxCorrections = strGetUnsigned (value);
+ if ( maxCorrections == 0 ) {
+ maxCorrections = (uint)-1;
+ }
break;
case OPT_SURNAMES:
doSurnames = strGetBoolean (value);
@@ -12266,28 +12323,46 @@
char tempName [1024];
const char * prevCorrection = "";
idNumberT id = 0;
- uint correctionCount = 0;
+ uint correctionCount = 0;
+
+ // Counters to monitor the crawl through the name base
+ //
+ uint maxName = nb->GetNumNames( nt );
+ uint thisName = 0;
+
+ // Thresholds for progress-bar updating
+ // We try to make about 200 steps, which should allow
+ // an update at least every second, even for a big name base.
+ //
+ uint nameThres = (maxName / 200) + 1;
+ uint corrThres = (maxCorrections / 200) + 1;
// Check every name of the specified type:
nb->IterateStart (nt);
while (nb->Iterate (nt, &id) == OK) {
- uint frequency = nb->GetFrequency (nt, id);
- // Do not bother trying to correct unused names:
- if (frequency == 0) { continue; }
-
+ uint frequency = nb->GetFrequency (nt, id);
+
+ // We have got the next name from the base
+ //
+ thisName++;
+
const char * name = nb->GetName (nt, id);
const char * origName = name;
- if (nt == NAME_PLAYER && !doSurnames && strIsSurnameOnly (name)) {
- continue;
- }
-
- // First, check for a general prefix or suffix correction:
int offset = 0;
const char * replace;
+ // Do not bother trying to correct unused names:
+ if (frequency == 0) { goto bar; }
+
+ if (nt == NAME_PLAYER && !doSurnames && strIsSurnameOnly (name)) {
+ goto bar;
+ }
+
+ // First, check for a general prefix or suffix correction:
+ //
replace = spellChecker[nt]->CorrectPrefix (name, &offset);
if (replace != NULL) {
if (correctionCount < maxCorrections) {
@@ -12300,7 +12375,7 @@
prevCorrection = origName;
}
correctionCount++;
- continue;
+ goto bar;
}
replace = spellChecker[nt]->CorrectSuffix (name, &offset);
@@ -12315,24 +12390,26 @@
prevCorrection = origName;
}
correctionCount++;
- continue;
+ goto bar;
}
-
- int replacedLength = 0;
- replace = spellChecker[nt]->CorrectInfix (name, &offset, &replacedLength);
- if (replace != NULL) {
- if (correctionCount < maxCorrections) {
- strCopy (tempName, name);
- strCopy (tempName + offset, replace);
- strAppend (tempName, &(name[offset + replacedLength]));
- sprintf (tempStr, "%s\"%s\"\t>> \"%s\" (%u)\n",
- *origName == *prevCorrection ? "" : "\n",
- origName, tempName, frequency);
- dstr->Append (tempStr);
- prevCorrection = origName;
- }
- correctionCount++;
- continue;
+
+ {
+ int replacedLength = 0;
+ replace = spellChecker[nt]->CorrectInfix (name, &offset, &replacedLength);
+ if (replace != NULL) {
+ if (correctionCount < maxCorrections) {
+ strCopy (tempName, name);
+ strCopy (tempName + offset, replace);
+ strAppend (tempName, &(name[offset + replacedLength]));
+ sprintf (tempStr, "%s\"%s\"\t>> \"%s\" (%u)\n",
+ *origName == *prevCorrection ? "" : "\n",
+ origName, tempName, frequency);
+ dstr->Append (tempStr);
+ prevCorrection = origName;
+ }
+ correctionCount++;
+ goto bar;
+ }
}
// If spellchecking names, remove any country code like " (USA)"
@@ -12347,85 +12424,132 @@
name = tempName;
}
}
+
+ {
+ const uint maxAmbiguous = 10;
+ uint count = 0;
+ const char * corrections [maxAmbiguous];
+ count = spellChecker[nt]->Corrections (name, corrections, maxAmbiguous);
- const uint maxAmbiguous = 10;
- uint count = 0;
- const char * corrections [maxAmbiguous];
- count = spellChecker[nt]->Corrections (name, corrections, maxAmbiguous);
-
- if (nt == NAME_PLAYER && count < maxAmbiguous) {
- // If correcting player names, also try the name with the text
- // after the last space moved to the start, e.g. "R. J. Fischer"
- // converted to "Fischer R. J.":
- strPromoteSurname (tempStr, name);
- count += spellChecker[nt]->Corrections (tempStr,
- &(corrections[count]), maxAmbiguous - count);
- // The above step can cause duplicated corrections, so
- // remove them:
- for (uint i=1; i < count; i++) {
- if (strEqual (corrections[i], corrections[i-1])) {
- for (uint j=i+1; j < count; j++) {
- corrections[j-1] = corrections[j];
+ if (nt == NAME_PLAYER && count < maxAmbiguous) {
+ // If correcting player names, also try the name with the text
+ // after the last space moved to the start, e.g. "R. J. Fischer"
+ // converted to "Fischer R. J.":
+ strPromoteSurname (tempStr, name);
+ count += spellChecker[nt]->Corrections( tempStr, &(corrections[count]), maxAmbiguous - count);
+ // The above step can cause duplicated corrections, so
+ // remove them:
+ for (uint i=1; i < count; i++) {
+ if (strEqual (corrections[i], corrections[i-1])) {
+ for (uint j=i+1; j < count; j++) {
+ corrections[j-1] = corrections[j];
+ }
+ count--;
}
- count--;
}
}
- }
-
- if (count > 1 && !ambiguous) { count = 0; }
-
- for (uint i=0; i < count; i++) {
- if (strEqual (origName, corrections[i])) { continue; }
- correctionCount++;
- if (correctionCount >= maxCorrections) { continue; }
-
- // Add correction to output, with a blank line first if the
- // correction starts with a different character to the
- // previous correction:
- sprintf (tempStr, "%s%s\"%s\"\t>> \"%s\" (%u)",
- *origName == *prevCorrection ? "" : "\n",
- count > 1 ? "Ambiguous: " : "",
- origName, corrections[i], frequency);
- dstr->Append (tempStr);
- if (nt == NAME_PLAYER) {
- // Look for a player birthdate:
- const char * text =
- spellChecker[nt]->GetCommentExact (corrections[i]);
- dateT birthdate = SpellChecker::GetBirthdate(text);
- dateT deathdate = SpellChecker::GetDeathdate(text);
- if (birthdate != ZERO_DATE || deathdate != ZERO_DATE) {
- dstr->Append (" ");
- if (birthdate != ZERO_DATE) {
- date_DecodeToString (birthdate, tempStr);
- dstr->Append(tempStr);
- }
- dstr->Append ("--");
- if (deathdate != ZERO_DATE) {
- date_DecodeToString (deathdate, tempStr);
- dstr->Append(tempStr);
+
+ // Handle ambiguous corrections, if wanted
+ //
+ if ( ambiguous || count == 1) {
+ for (uint i=0; i < count; i++) {
+
+ // No need to include onself. Skip.
+ //
+ if (strEqual (origName, corrections[i])) {
+ continue; // to next ambiguous candidate
+ }
+
+ // We have a new one
+ //
+ correctionCount++;
+
+ // Add correction to output, with a blank line first if the
+ // correction starts with a different character to the
+ // previous correction:
+ sprintf (tempStr, "%s%s\"%s\"\t>> \"%s\" (%u)",
+ *origName == *prevCorrection ? "" : "\n",
+ count > 1 ? "Ambiguous: " : "",
+ origName, corrections[i], frequency);
+ dstr->Append (tempStr);
+ if (nt == NAME_PLAYER) {
+ // Look for a player birthdate:
+ const char * text =
+ spellChecker[nt]->GetCommentExact (corrections[i]);
+ dateT birthdate = SpellChecker::GetBirthdate(text);
+ dateT deathdate = SpellChecker::GetDeathdate(text);
+ if (birthdate != ZERO_DATE || deathdate != ZERO_DATE) {
+ dstr->Append (" ");
+ if (birthdate != ZERO_DATE) {
+ date_DecodeToString (birthdate, tempStr);
+ dstr->Append(tempStr);
+ }
+ dstr->Append ("--");
+ if (deathdate != ZERO_DATE) {
+ date_DecodeToString (deathdate, tempStr);
+ dstr->Append(tempStr);
+ }
}
}
- }
- dstr->Append ("\n");
- prevCorrection = origName;
-
- }
+ dstr->Append ("\n");
+ prevCorrection = origName;
+ }
+ }
+ }
+
+ // Update the progress bar
+ //
+
+ bar:
+
+ if ( showProgress ) {
+ // Update filter to avoid hyperactivity
+ //
+ bool filter = (thisName % nameThres == 1)
+ || (correctionCount % corrThres == 1);
+
+ // Try to be clever here: If we go for maxCorrections only, we do not know if and when
+ // they will be found. So we base our progress indicator on either the name base crawl
+ // or the actual correction counter, whichever is closer to its finish.
+ //
+ if ( filter ) {
+ if ( (double)correctionCount / (double)maxCorrections > (double)thisName / (double)maxName ) {
+ updateProgressBar( ti, correctionCount, maxCorrections );
+ }
+ else {
+ updateProgressBar( ti, thisName, maxName );
+ }
+
+ // Allow the user to break in at this point
+ //
+ if ( (interrupted = interruptedProgress()) ) {
+ break;
+ }
+ }
+ }
+
+ // Bail out once we have found maxCorrections
+ //
+ if ( correctionCount >= maxCorrections ) {
+ break;
+ }
+ }
+
+ // Ensure a truely full bar at this point, but only do so if
+ // the user chose to run the thing till the very end.
+ //
+ if ( ! interrupted ) {
+ if ( showProgress ) {
+ updateProgressBar (ti, 1, 1);
+ }
}
// Now generate the return message:
- sprintf (tempStr, "Scid found %u %s name correction%s",
+ sprintf (tempStr, "Scid found %u %s name correction%s.\n",
correctionCount, NAME_TYPE_STRING[nt],
strPlural (correctionCount));
Tcl_AppendResult (ti, tempStr, NULL);
- if (correctionCount > maxCorrections) {
- sprintf (tempStr, ", the first %u are listed below.", maxCorrections);
- } else if (correctionCount > 0) {
- strCopy (tempStr, ", all are listed below.");
- } else {
- strCopy (tempStr, ".");
- }
- Tcl_AppendResult (ti, tempStr, "\n", NULL);
Tcl_AppendResult (ti,
"Edit the list to remove any corrections you do not want.\n",
Index: tcl/file/maint.tcl
===================================================================
RCS file: /cvsroot/scid/scid/tcl/file/maint.tcl,v
retrieving revision 1.11
diff -u -r1.11 maint.tcl
--- tcl/file/maint.tcl 11 Jan 2009 16:03:29 -0000 1.11
+++ tcl/file/maint.tcl 3 Mar 2009 18:38:20 -0000
@@ -1439,8 +1439,16 @@
catch {grab $w}
}
+# Maximum nr of corrections to be scanned
+# Set to zero to find them all
+# Set to some positive number to limit
+#
+set cleaner_maxSpellCorrections 0
+
+
proc doCleaner {} {
global cleaner twinSettings
+ global cleaner_maxSpellCorrections
set answer [tk_dialog .mtoolDialog "Scid" \
[string trim $::tr(CleanerConfirm)] "" \
@@ -1483,7 +1491,7 @@
mtoolAdd $t "$count: $::tr(Spellchecking): $::tr($names)..."
incr count
set result "0 $nameType names were corrected."
- if {! [catch {sc_name spellcheck -max 100000 $nameType} corrections]} {
+ if {! [catch {sc_name spellcheck -max $cleaner_maxSpellCorrections $nameType} corrections]} {
update
catch {sc_name correct $nameType $corrections} result
}
Index: tcl/file/spellchk.tcl
===================================================================
RCS file: /cvsroot/scid/scid/tcl/file/spellchk.tcl,v
retrieving revision 1.3
diff -u -r1.3 spellchk.tcl
--- tcl/file/spellchk.tcl 23 Dec 2008 20:10:46 -0000 1.3
+++ tcl/file/spellchk.tcl 3 Mar 2009 18:38:20 -0000
@@ -3,10 +3,23 @@
### Copyright (C) 2000-2003 Shane Hudson.
set spellcheckType Player
-set spell_maxCorrections 2000
+
+# Maximum nr of corrections to be scanned
+# Set to zero to find them all
+# Set to some positive number to limit
+#
+set spell_maxCorrections 0
+
set spellcheckSurnames 0
set spellcheckAmbiguous 1
+# Remember what we are doing, being
+# - "idle" - nothing special
+# - "scanning" - finding corrections
+# - "correcting" - making corrections
+#
+set spellstate idle
+
# readSpellCheckFile:
# Presents a File Open dialog box for a Scid spellcheck file,
# then tries to read the file. If the parameter "message" is true
@@ -34,118 +47,245 @@
return 1
}
-proc updateSpellCheckWin {type} {
- global spellcheckType spell_maxCorrections spellcheckSurnames
- global spellcheckAmbiguous
- busyCursor .
- .spellcheckWin.text.text delete 1.0 end
- #.spellcheckWin.text.text insert end "Finding player corrections..."
- update idletasks
- catch {sc_name spellcheck -max $spell_maxCorrections \
- -surnames $spellcheckSurnames \
- -ambiguous $spellcheckAmbiguous $type} result
- .spellcheckWin.text.text delete 1.0 end
- .spellcheckWin.text.text insert end $result
- unbusyCursor .
+# Set the environment when the correction scan starts
+#
+proc startScanning {} {
+ global spellstate
+ global spellcheckType
+
+ # Remember that we are scanning
+ #
+ set spellstate scanning
+
+ # Disable all buttons except the cancel button that we
+ # transfer into a stop button
+ #
+ .spellcheckWin.buttons.ambig configure -state disabled
+ .spellcheckWin.buttons.ok configure -state disabled
+ .spellcheckWin.buttons.cancel configure -text "Stop"
+ bind .spellcheckWin <Alt-s> ".spellcheckWin.buttons.cancel invoke; break"
+ if {$spellcheckType == "Player"} {
+ .spellcheckWin.buttons.surnames configure -state disabled
+ }
}
-proc openSpellCheckWin {type {parent .}} {
- global spellcheckType spell_maxCorrections spellcheckSurnames
- global spellcheckAmbiguous
- set w .spellcheckWin
- if {[winfo exists $w]} {
- tk_messageBox -type ok -icon info -title "Scid: Spellcheck error" \
- -parent $parent \
- -message "The spellcheck window is already open; close it first."
- return
- }
- if {[lindex [sc_name read] 0] == 0} {
- # No spellcheck file loaded, so try to open one:
- if {![readSpellCheckFile]} {
- return
+# Set the environment when the correction scan stops
+#
+proc stopScanning {} {
+ global spellstate
+ global spellcheckType
+
+ # Remember that we are not scanning
+ #
+ set spellstate idle
+
+ # Enable all buttons and set the cancel button back
+ #
+ .spellcheckWin.buttons.ambig configure -state enabled
+ .spellcheckWin.buttons.ok configure -state enabled
+ .spellcheckWin.buttons.cancel configure -text "Cancel"
+ bind .spellcheckWin <Alt-c> ".spellcheckWin.buttons.cancel invoke; break"
+ if {$spellcheckType == "Player"} {
+ .spellcheckWin.buttons.surnames configure -state enabled
}
- }
- busyCursor .
- if {[catch {sc_name spellcheck -max $spell_maxCorrections \
- -surnames $spellcheckSurnames \
- -ambiguous $spellcheckAmbiguous $type} result]} {
- unbusyCursor .
- tk_messageBox -type ok -icon info -title "Scid: Spellcheck results" \
- -parent $parent -message $result
- return
- }
- unbusyCursor .
- set spellcheckType $type
+}
- toplevel $w
- wm title $w "Scid: Spellcheck Results"
- wm minsize $w 50 10
-
- bind $w <F1> { helpWindow Maintenance }
- bind $w <Configure> "recordWinSize $w"
-
- set f [ttk::frame $w.buttons]
- pack $f -side bottom -ipady 1 -fill x
-
-ttk::checkbutton $f.ambig -variable spellcheckAmbiguous \
- -text "Ambiguous" -command "updateSpellCheckWin $type"
- pack $f.ambig -side left -padx 2 -ipady 2 -ipadx 3
- if {$type == "Player"} {
- ttk::checkbutton $f.surnames -variable spellcheckSurnames \
- -text "Surnames" -command "updateSpellCheckWin Player"
- pack $f.surnames -side left -padx 2 -ipady 2 -ipadx 3
- }
- ttk::button $f.ok -text "Make Corrections" -underline 0 -command {
+# Set the environment when correction starts
+#
+proc startCorrecting {} {
+ global spellstate
+ global spellcheckType
+
+ # Remember that we are correcting
+ #
+ set spellstate correcting
+
+ # Disable all buttons except the cancel button that we
+ # transfer into a stop button
+ #
+ .spellcheckWin.buttons.ambig configure -state disabled
+ .spellcheckWin.buttons.ok configure -state disabled
+ .spellcheckWin.buttons.cancel configure -text "Stop"
+ bind .spellcheckWin <Alt-s> ".spellcheckWin.buttons.cancel invoke; break"
+ if {$spellcheckType == "Player"} {
+ .spellcheckWin.buttons.surnames configure -state disabled
+ }
+}
+
+
+# Start the correction scan and dump the results into the
+# text window. After this the user may edit the correction
+# 'script' and actually make the corrections.
+#
+# While the scan is running, all buttons except a stop button
+# are disabled.
+#
+proc updateSpellCheckWin {type} {
+ global spellcheckType spell_maxCorrections spellcheckSurnames
+ global spellcheckAmbiguous
+
busyCursor .
- set spelltext ""
- catch {set spelltext [.spellcheckWin.text.text get 1.0 end-1c]}
.spellcheckWin.text.text delete 1.0 end
- .spellcheckWin.text.text insert end \
- "Scid is making the spelling corrections.\nPlease wait..."
+ .spellcheckWin.text.text insert end "Scid is finding spelling corrections.\nPlease wait..."
+
+ # Enable the progress bar
+ #
+ sc_progressBar .spellcheckWin.progress bar 451 21 time
+
+ startScanning
+
update idletasks
- set spell_result ""
- set result [catch {sc_name correct $spellcheckType $spelltext} spell_result]
- set messageIcon info
- if {$result} { set messageIcon error }
- tk_messageBox -type ok -parent .spellcheckWin -icon $messageIcon \
- -title "Scid: Spellcheck results" -message $spell_result
+ if {[catch {sc_name spellcheck -max $spell_maxCorrections \
+ -surnames $spellcheckSurnames \
+ -ambiguous $spellcheckAmbiguous $type} result]} {
+ stopScanning
+ unbusyCursor .
+ tk_messageBox -type ok -icon info -title "Scid: Spellcheck results" \
+ -parent $parent -message $result
+ return
+ }
+ stopScanning
+
+ .spellcheckWin.text.text delete 1.0 end
+ .spellcheckWin.text.text insert end $result
unbusyCursor .
- focus .
- destroy .spellcheckWin
- sc_game tags reload
- updateBoard -pgn
- ::windows::gamelist::Refresh
- }
- bind $w <Alt-m> "$f.ok invoke; break"
+}
- ttk::button $f.cancel -text "Cancel" -underline 0 -command {
- focus .
- destroy .spellcheckWin
- }
- bind $w <Alt-c> "$f.cancel invoke; break"
- pack $f.cancel $f.ok -side right -padx 5
+# Create the spell checking window with its event handlers
+# and start the initial correction scan
+#
+proc openSpellCheckWin {type {parent .}} {
+ global spellcheckType spellcheckSurnames
+ global spellcheckAmbiguous
+ global spellstate
+
+ set w .spellcheckWin
+
+ if {[winfo exists $w]} {
+ tk_messageBox -type ok -icon info -title "Scid: Spellcheck error" \
+ -parent $parent \
+ -message "The spellcheck window is already open; close it first."
+ return
+ }
+
+ if {[lindex [sc_name read] 0] == 0} {
+ # No spellcheck file loaded, so try to open one:
+ if {![readSpellCheckFile]} {
+ return
+ }
+ }
+ set spellcheckType $type
- set f [ttk::frame $w.text]
- pack $w.text -expand yes -fill both
- ttk::scrollbar $f.ybar -command "$f.text yview"
- ttk::scrollbar $f.xbar -orient horizontal -command "$f.text xview"
- text $f.text -yscrollcommand "$f.ybar set" -xscrollcommand "$f.xbar set" \
- -setgrid 1 -width $::winWidth($w) -height $::winHeight($w) \
- -background white -wrap none
- $f.text configure -tabs \
- [font measure font_Regular "xxxxxxxxxxxxxxxxxxxxxxxxx"]
-
- grid $f.text -row 0 -column 0 -sticky news
- grid $f.ybar -row 0 -column 1 -sticky news
- grid $f.xbar -row 1 -column 0 -sticky news
+ toplevel $w
+ wm title $w "Scid: Spellcheck Results"
+ wm minsize $w 50 10
+
+ bind $w <F1> { helpWindow Maintenance }
+ bind $w <Configure> "recordWinSize $w"
+
+ # Create the button pad at the bottom of the window
+ #
+ set f [ttk::frame $w.buttons]
+ pack $f -side bottom -ipady 1 -fill x
+
+ # Draw a canvas ("progress") to hold the progress bar
+ # and put it above the buttons at the bottom of the window
+ #
+ canvas $w.progress -width 450 -height 20 -bg white -relief solid -border 1
+ $w.progress create rectangle 0 0 0 0 -fill blue -outline blue -tags bar
+ $w.progress create text 445 10 -anchor e -font font_Regular -tags time \
+ -fill black -text "0:00 / 0:00"
+ pack $w.progress -side bottom
+
+ # The ambiguous check mark
+ # Hitting it starts a new correction scan
+ ttk::checkbutton $f.ambig -variable spellcheckAmbiguous \
+ -text "Ambiguous" -command "updateSpellCheckWin $type"
+ pack $f.ambig -side left -padx 2 -ipady 2 -ipadx 3
+
+ # When correcting player names, we add a surnames option
+ #
+ if {$type == "Player"} {
+ # The surnames check mark
+ # Hitting it starts a new correction scan
+ #
+ ttk::checkbutton $f.surnames -variable spellcheckSurnames \
+ -text "Surnames" -command "updateSpellCheckWin Player"
+ pack $f.surnames -side left -padx 2 -ipady 2 -ipadx 3
+ }
- grid rowconfig $w.text 0 -weight 1 -minsize 0
- grid columnconfig $w.text 0 -weight 1 -minsize 0
+ # The button to start the correction making...
+ #
+ ttk::button $f.ok -text "Make Corrections" -underline 0 -command {
+ busyCursor .
+ set spelltext ""
+ catch {set spelltext [.spellcheckWin.text.text get 1.0 end-1c]}
+ .spellcheckWin.text.text delete 1.0 end
+ .spellcheckWin.text.text insert end \
+ "Scid is making the spelling corrections.\nPlease wait..."
+
+ # Enable the progress bar
+ #
+ sc_progressBar .spellcheckWin.progress bar 451 21 time
+
+ update idletasks
+ set spell_result ""
+ startCorrecting
+ set result [catch {sc_name correct $spellcheckType $spelltext} spell_result]
+ set messageIcon info
+ if {$result} { set messageIcon error }
+ tk_messageBox -type ok -parent .spellcheckWin -icon $messageIcon \
+ -title "Scid: Spellcheck results" -message $spell_result
+ unbusyCursor .
+ focus .
+ destroy .spellcheckWin
+ sc_game tags reload
+ updateBoard -pgn
+ ::windows::gamelist::Refresh
+ }
+ bind $w <Alt-m> "$f.ok invoke; break"
+
+ # The cancel button operates in an either/or context
+ # While some process is running, it simply stops it
+ # In other cases, spell checking is left
+ #
+ ttk::button $f.cancel -text "Cancel" -underline 0 -command {
+ if {$spellstate == "scanning" || $spellstate == "correcting"} {
+ sc_progressBar
+ } else {
+ focus .
+ destroy .spellcheckWin
+ }
+ }
+ bind $w <Alt-c> "$f.cancel invoke; break"
+ pack $f.cancel $f.ok -side right -padx 5
- $f.text insert end $result
- focus $f.text
+ # Prepare the text pad
+ #
+ set f [ttk::frame $w.text]
+ pack $w.text -expand yes -fill both
+ ttk::scrollbar $f.ybar -command "$f.text yview"
+ ttk::scrollbar $f.xbar -orient horizontal -command "$f.text xview"
+ text $f.text -yscrollcommand "$f.ybar set" -xscrollcommand "$f.xbar set" \
+ -setgrid 1 -width $::winWidth($w) -height $::winHeight($w) \
+ -background white -wrap none
+ $f.text configure -tabs \
+ [font measure font_Regular "xxxxxxxxxxxxxxxxxxxxxxxxx"]
+
+ grid $f.text -row 0 -column 0 -sticky news
+ grid $f.ybar -row 0 -column 1 -sticky news
+ grid $f.xbar -row 1 -column 0 -sticky news
+
+ grid rowconfig $w.text 0 -weight 1 -minsize 0
+ grid columnconfig $w.text 0 -weight 1 -minsize 0
+
+ focus $f.text
+
+ # Start the initial search for spelling corrections
+ #
+ updateSpellCheckWin $type
}
------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Scid-users mailing list
Scid-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/scid-users