Index: openacs-4/bin/webspell
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/bin/webspell,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/bin/webspell 30 Sep 2003 19:27:48 -0000 1.1
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Wrapper for aspell/ispell that sets the HOME environment variable.
+# Can't seem to do this from AOLserver Tcl.
+# Takes three arguments: file to spellcheck, dictionary file, language.
+#
+# Root must be able to execute this file if AOLserver runs as root
+# (which it does if it runs on a privileged port, e.g., port 80)
+
+#HOME=/usr/local/aolserver
+HOME=$4
+export HOME
+exec $3 $5 -a -p $2 < $1
Index: openacs-4/packages/acs-tcl/tcl/form-processing-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/form-processing-procs.tcl,v
diff -u -r1.36 -r1.37
--- openacs-4/packages/acs-tcl/tcl/form-processing-procs.tcl 29 Sep 2003 13:20:55 -0000 1.36
+++ openacs-4/packages/acs-tcl/tcl/form-processing-procs.tcl 30 Sep 2003 19:27:48 -0000 1.37
@@ -424,6 +424,19 @@
+
+ Define an element of type text with spell-checking disabled. In case spell-checking is enabled globally
+ for the widget of this element ("text" in the example), the "nospell" flag will override that parameter
+ and disable spell-checking on this particular element. Currently, spell-checking can be enabled for
+ these widgets: text, textarea, and richtext.
+
+
+
+
@see ad_form_new_p
@see ad_set_element_value
@see ad_set_form_values
@@ -711,7 +724,8 @@
}
}
- optional {
+ nospell -
+ optional {
if { ![empty_string_p $af_element_parameters($element_name:$flag)] } {
return -code error "element $element_name: $flag attribute can not have a parameter"
}
Index: openacs-4/packages/acs-templating/acs-templating.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/acs-templating.info,v
diff -u -r1.16 -r1.17
--- openacs-4/packages/acs-templating/acs-templating.info 22 Sep 2003 18:03:48 -0000 1.16
+++ openacs-4/packages/acs-templating/acs-templating.info 30 Sep 2003 19:27:49 -0000 1.17
@@ -7,7 +7,7 @@
tt
-
+ Karl Goldstein
@@ -19,7 +19,7 @@
template system provides a way to use a single layout
specification for many physical pages, so the overall layout of a site can be more easily administered.
-
+
@@ -32,6 +32,9 @@
+
+
+
Index: openacs-4/packages/acs-templating/tcl/element-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/element-procs.tcl,v
diff -u -r1.15 -r1.16
--- openacs-4/packages/acs-templating/tcl/element-procs.tcl 22 Sep 2003 13:47:35 -0000 1.15
+++ openacs-4/packages/acs-templating/tcl/element-procs.tcl 30 Sep 2003 19:27:49 -0000 1.16
@@ -115,6 +115,9 @@
the user to edit the contents. If set to the empty string or
not specified at all, the form's 'mode' setting is used instead.
+ @option nospell A flag indicating that no spell-checking should be performed on
+ this element. This overrides the 'SpellcheckFormWidgets' parameter.
+
@option before_html A chunk of HTML displayed immediately before the rendered element.
@option after_html A chunk of HTML displayed immediately after the rendered element.
@@ -523,7 +526,12 @@
} else {
set values [template::data::transform::$datatype element]
}
-
+
+ if { [lindex [template::util::spellcheck::spellcheck_properties -element_ref element] 0] } {
+
+ set values [template::data::transform::spellcheck -element_ref element -values $values]
+ }
+
return $values
}
Index: openacs-4/packages/acs-templating/tcl/richtext-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/richtext-procs.tcl,v
diff -u -r1.8 -r1.9
--- openacs-4/packages/acs-templating/tcl/richtext-procs.tcl 22 Sep 2003 14:53:37 -0000 1.8
+++ openacs-4/packages/acs-templating/tcl/richtext-procs.tcl 30 Sep 2003 19:27:49 -0000 1.9
@@ -187,6 +187,18 @@
append output [textarea_internal "$element(id)" attributes $contents]
append output " Format: [menu "$element(id).format" [template::util::richtext::format_options] $format {}]"
+ set spellcheck_properties [template::util::spellcheck::spellcheck_properties -element_ref element]
+ set spellcheck_p [lindex $spellcheck_properties 0]
+
+ if { $spellcheck_p } {
+ set yes_checked [lindex $spellcheck_properties 1]
+ set no_checked [lindex $spellcheck_properties 2]
+ append output " Spellcheck?
+ Yes \n
+ No"
+
+ }
+
} else {
# Display mode
if { [info exists element(value)] } {
Index: openacs-4/packages/acs-templating/tcl/spellcheck-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/spellcheck-procs.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-templating/tcl/spellcheck-procs.tcl 30 Sep 2003 19:27:49 -0000 1.1
@@ -0,0 +1,372 @@
+ad_library {
+ Spell-check library for OpenACS templating system.
+
+ @author Ola Hansson (ola@polyxena.net)
+ @creation-date 2003-09-21
+ @cvs-id $Id: spellcheck-procs.tcl,v 1.1 2003/09/30 19:27:49 olah Exp $
+}
+
+namespace eval template::util::spellcheck {}
+
+ad_proc -public template::util::spellcheck { command args } {
+ Dispatch procedure for the spellcheck object
+} {
+ eval template::util::spellcheck::$command $args
+}
+
+ad_proc -public template::util::spellcheck::merge_text { element_id } {
+ Returns the merged (possibly corrected) text or the empty string
+ if it is not time to merge.
+} {
+ set merge_text [ns_queryget $element_id.merge_text]
+
+ if { [empty_string_p $merge_text] } {
+ return {}
+ }
+
+ # loop through errors and substitute the corrected words for #errnum#.
+ set i 0
+ while { [ns_queryexists $element_id.error_$i] } {
+ regsub "\#$i\#" $merge_text [ns_queryget $element_id.error_$i] merge_text
+ incr i
+ }
+
+ return $merge_text
+}
+
+ad_proc -public template::data::transform::spellcheck {
+ -element_ref:required
+ -values:required
+} {
+ upvar $element_ref element
+
+ # case 1, initial submission of non-checked text: returns {}.
+ # case 2, submission of the page showing errors: returns the corrected text.
+ set merge_text [template::util::spellcheck::merge_text $element(id)]
+
+ if { [set richtext_p [string equal "richtext" $element(datatype)]] } {
+ # special treatment for the "richtext" datatype.
+ set format [template::util::richtext::get_property format [lindex $values 0]]
+ if { ![empty_string_p $merge_text] } {
+ return [list [list $merge_text [ns_queryget $element(id).format]]]
+ }
+ set contents [template::util::richtext::get_property contents [lindex $values 0]]
+ } else {
+ if { ![empty_string_p $merge_text] } {
+ return [list $merge_text]
+ }
+ set contents [lindex $values 0]
+ }
+
+ if { [empty_string_p $contents] } {
+ return [list]
+ }
+
+ set spellcheck_p [ad_decode [ns_queryget $element(id).spellcheck_p] 1 1 0]
+
+ # perform spellchecking or not?
+ if { $spellcheck_p } {
+
+ template::util::spellcheck::get_element_formtext \
+ -text $contents \
+ -var_to_spellcheck $element(id) \
+ -error_num_ref error_num \
+ -formtext_to_display_ref formtext_to_display \
+ -just_the_errwords_ref {} \
+ -html
+
+ if { $error_num > 0 } {
+ # there was at least one error.
+
+ template::element::set_error $element(form_id) $element(id) "
+ [ad_decode $error_num 1 "Found one error." "Found $error_num errors."] Please correct, if necessary."
+
+ # switch to display mode so we can show our inline mini-form with suggestions.
+ template::element::set_properties $element(form_id) $element(id) mode display
+
+ if { $richtext_p } {
+ append formtext_to_display "
+"
+ }
+
+ # This is needed in order to display the form text noquoted in the "show errors" page ...
+ template::element::set_properties $element(form_id) $element(id) -display_value $formtext_to_display
+
+ set contents $formtext_to_display
+ }
+ }
+
+ # no spellchecking was to take place, or there were no errors.
+ if { $richtext_p } {
+ return [list [list $contents $format]]
+ } else {
+ return [list $contents]
+ }
+}
+
+ad_proc -public template::util::spellcheck::get_sorted_list_with_unique_elements {
+ -the_list:required
+} {
+
+ Converts a list of possibly duplicate elements (words) into a sorted list where no duplicates exist.
+
+ @param the_list The list of possibly duplicate elements.
+
+} {
+
+ set sorted_list [lsort -dictionary $the_list]
+ set new_list [list]
+
+ set old_element "XXinitial_conditionXX"
+ foreach list_element $sorted_list {
+ if { ![string equal $list_element $old_element] } {
+ lappend new_list $list_element
+ }
+ set old_element $list_element
+ }
+
+ return $new_list
+
+}
+
+ad_proc -public template::util::spellcheck::get_element_formtext {
+ -text:required
+ {-html:boolean 0}
+ -var_to_spellcheck:required
+ -error_num_ref:required
+ -formtext_to_display_ref:required
+ {-just_the_errwords_ref ""}
+} {
+
+ @param text The string to check for spelling errors.
+
+ @param html_p Does the text have html in it? If so, we strip out html tags in the string we feed to ispell (or aspell).
+
+ @param var_to_spellcheck The name of the text input type or textarea that holds this text (eg., "email_body")
+
+} {
+
+ # We need a "var_to_spellcheck" argument so that we may name the hidden errnum vars
+ # differently on each input field by prepending the varname.
+
+ set text_to_spell_check $text
+
+ # if HTML then substitute out all HTML tags
+ if { $html_p } {
+ regsub -all {<[^<]*>} $text_to_spell_check "" text_to_spell_check
+ }
+
+ set tmpfile [ns_mktemp "/tmp/webspellXXXXXX"]
+ set f [open $tmpfile w]
+ puts $f $text_to_spell_check
+ close $f
+
+ set lines [split $text "\n"]
+
+ set dictionaryfile [file join [acs_package_root_dir acs-templating] resources forms ispell-words]
+
+ # The webspell wrapper is necessary because ispell requires
+ # the HOME environment set, and setting env(HOME) doesn't appear
+ # to work from AOLserver.
+
+ set spelling_wrapper [file join [acs_root_dir] bin webspell]
+
+ set spellchecker_path [parameter::get_from_package_key \
+ -package_key acs-templating \
+ -parameter SpellcheckerPath \
+ -default /usr/bin/aspell]
+
+ set language [parameter::get_from_package_key \
+ -package_key acs-templating \
+ -parameter SpellcheckLang \
+ -default {}]
+
+ # the --lang switch only works with aspell and if it is not present
+ # aspell's (or ispell's) default language will have to do.
+ if { ![empty_string_p $language] } {
+ set language "--lang=$language"
+ }
+
+ set ispell_proc [open "|$spelling_wrapper $tmpfile $dictionaryfile $spellchecker_path [ns_info home] $language" r]
+
+ # read will occasionally error out with "interrupted system call",
+ # so retry a few times in the hopes that it will go away.
+ set try 0
+ set max_retry 10
+ while { [catch { set ispell_text [read -nonewline $ispell_proc] } errmsg]
+ && $try < $max_retry } {
+ incr try
+ ns_log Notice "spellchecker had a problem: $errmsg"
+ }
+
+ if { [catch [close $ispell_proc] errmsg] } {
+ ad_return_error "No Dictionary Found" "Spell-checking is enabled but the spell-check program could not be executed. Check the SpellcheckerPath parameter in acs-templating. Also check the permissions on the spell-check program.
Here is the error message:
$errmsg
"
+ ad_script_abort
+ }
+
+ ns_unlink $tmpfile
+
+ if { $try == $max_retry } {
+ return -code error "webspell: Tried to execute spellchecker $max_retry times but it did not work out. Sorry!"
+ }
+
+ ####
+ #
+ # Ispell is done. Start manipulating the result string.
+ #
+ ####
+
+ set ispell_lines [split $ispell_text "\n"]
+ # Remove the version line.
+ if { [llength $ispell_lines] > 0 } {
+ set ispell_lines [lreplace $ispell_lines 0 0]
+ }
+
+ ####
+ # error_num
+ ####
+ upvar $error_num_ref error_num
+
+ set error_num 0
+ set errors [list]
+
+ set processed_text ""
+
+ set line [lindex $lines 0]
+
+ foreach ispell_line $ispell_lines {
+ switch -glob -- $ispell_line {
+ \#* {
+ regexp "^\# (\[^ \]+) (\[0-9\]+)" $ispell_line dummy word pos
+ regsub $word $line "\#$error_num\#" line
+ lappend errors [list miss $error_num $word]
+ incr error_num
+ }
+ &* {
+ regexp {^& ([^ ]+) ([0-9]+) ([0-9]+): (.*)$} $ispell_line dummy word n_options pos options
+ regsub $word $line "\#$error_num\#" line
+ lappend errors [list nearmiss $error_num $word $options]
+ incr error_num
+ }
+ "" {
+ append processed_text "$line\n"
+ if { [llength $lines] > 0 } {
+ set lines [lreplace $lines 0 0]
+ set line [lindex $lines 0]
+ }
+ }
+ }
+ }
+
+ set formtext $processed_text
+
+ foreach { errtype errnum errword erroptions } [join $errors] {
+ set wordlen [string length $errword]
+
+ if { [string equal "miss" $errtype] } {
+ regsub "\#$errnum\#" $formtext "" formtext
+ } elseif { [string equal "nearmiss" $errtype] } {
+ regsub -all ", " $erroptions "," erroptions
+ set options [split $erroptions ","]
+ set select_text ""
+ regsub "\#$errnum\#" $formtext $select_text formtext
+ }
+ }
+
+ ####
+ # formtext_to_display
+ ####
+ upvar $formtext_to_display_ref formtext_to_display
+
+ regsub -all "\r\n" $formtext " " formtext_to_display
+
+ # We replace with because misspelled text in link titles
+ # would lead to strange browser behaviour where the select boxes with the
+ # proposed changes would itself be a link!!!
+ # It seemed like an okay idea to make the text underlined so it would a) work,
+ # b) still resemble a link ...
+ regsub -all {} $formtext_to_display "" formtext_to_display
+ regsub -all {} $formtext_to_display "" formtext_to_display
+
+ append formtext_to_display ""
+
+
+ ####
+ # just_the_errwords
+ ####
+
+ if { ![empty_string_p $just_the_errwords_ref]} {
+
+ upvar $just_the_errwords_ref just_the_errwords
+
+ set just_the_errwords [list]
+ foreach err $errors {
+ lappend just_the_errwords [lindex $err 2]
+ }
+
+ }
+}
+
+ad_proc -public template::util::spellcheck::spellcheck_properties {
+ -element_ref:required
+} {
+ Returns a list of spellcheck properties.
+} {
+ upvar $element_ref element
+
+ if { [empty_string_p [set spellcheck_p [ns_queryget $element(id).spellcheck_p]]] } {
+
+ # The user hasn't been able to state whether (s)he wants spellchecking to be performed or not.
+ # That's either because spell-checking is disabled for this element, or we're not dealing with a submit.
+ # Whichever it is, let's see if, and then how, we should render the spellcheck "sub widget".
+
+ array set widget_info [string trim [parameter::get_from_package_key -package_key acs-templating \
+ -parameter SpellcheckFormWidgets \
+ -default ""]]
+
+ set spellcheck_p [expr [array size widget_info] \
+ && ![info exists element(nospell)] \
+ && ([string equal $element(widget) "richtext"] || [string equal $element(widget) "text"] || [string equal $element(widget) "textarea"]) \
+ && [lsearch -exact [array names widget_info] $element(widget)] != -1]
+
+ if { $spellcheck_p } {
+ # This is not a submit; we are rendering the form element for the first time.
+ # Since the spellcheck "sub widget" is to be displayed we'll also want to know
+ # whether it is the "Yes" or the "No" button that should be pressed by default.
+ if { $widget_info(${element(widget)}) } {
+ set yes_checked "checked"
+ set no_checked ""
+ } else {
+ set yes_checked ""
+ set no_checked "checked"
+ }
+ } else {
+ # set these to something so the script won't choke.
+ set yes_checked "n/a"
+ set no_checked "n/a"
+ }
+
+ } else {
+
+ # The user has explicitly stated if (s)he wants spellchecking to be performed on the text or not.
+ # Hence we are in submit mode with spell-checking enabled (radio button true or false).
+ # Let's check which it is and keep record of the states of our radio buttons in case the error
+ # page is shown.
+
+ if { $spellcheck_p } {
+ set yes_checked "checked"
+ set no_checked ""
+ } else {
+ set yes_checked ""
+ set no_checked "checked"
+ set spellcheck_p 1
+ }
+
+ }
+
+ return [list $spellcheck_p $yes_checked $no_checked]
+}
Index: openacs-4/packages/acs-templating/tcl/widget-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/widget-procs.tcl,v
diff -u -r1.23 -r1.24
--- openacs-4/packages/acs-templating/tcl/widget-procs.tcl 22 Sep 2003 21:45:31 -0000 1.23
+++ openacs-4/packages/acs-templating/tcl/widget-procs.tcl 30 Sep 2003 19:27:49 -0000 1.24
@@ -209,6 +209,17 @@
set output [textarea_internal $element(name) attributes $value $mode]
+ set spellcheck_properties [template::util::spellcheck::spellcheck_properties -element_ref element]
+ set spellcheck_p [lindex $spellcheck_properties 0]
+
+ if { $spellcheck_p } {
+ set yes_checked [lindex $spellcheck_properties 1]
+ set no_checked [lindex $spellcheck_properties 2]
+ append output " Spellcheck?
+ Yes \n
+ No"
+ }
+
return $output
}
@@ -321,7 +332,18 @@
upvar $element_reference element
- return [input text element $tag_attributes]
+ set spellcheck_properties [template::util::spellcheck::spellcheck_properties -element_ref element]
+ set spellcheck_p [lindex $spellcheck_properties 0]
+
+ if { [string equal $element(mode) "edit"] && $spellcheck_p } {
+ set yes_checked [lindex $spellcheck_properties 1]
+ set no_checked [lindex $spellcheck_properties 2]
+ return "[input text element $tag_attributes] Spellcheck?
+ Yes \n
+ No"
+ } else {
+ return [input text element $tag_attributes]
+ }
}