program to add some spell checking functionality to your program.
The win32 version of Aspell as well as some language packs can be downloaded here:
http://aspell.net/win32/
My example uses Aspell in "pipe" mode. There is also a C api to access a dll or static lib,
but i did not get this to run right away, and this method is much simpler to do imho.
The example shows the basic stuff required to check the spelling. Aspell provides
much more stuff like adding words to a personal/global dictionary and so on.
Just look at the docs at http://aspell.sourceforge.net/ for more information.
Enjoy...
Code: Select all
; Example of easy spell-checking using the GNU Aspell spellchecker.
;
; The win32 port of Aspell as well as a number of ready to use language packs
; can be found here: http://aspell.net/win32/
;
; Download the package, install it and run this code.
;
; Aspell works quite simple:
; After starting the program with the "-a" option, it outputs one line of Version
; information, then waits for input. To check a line, simply write it to the
; Aspell program with WriteProgramStringN() (note the 'N' to write a newline!)
; Best is to append one "^" before the text to make sure it is not interpreted as a command.
;
; Aspell will return this (each on a single line):
; only "*" for each correct word in the input (this can be disabled, see the aspell manual)
; "# oldword wordoffset" for a wrong word with no suggestions (offset is the index of the wordstart in the input)
; "& oldword suggestioncount wordoffset: suggestion1, suggestion2, ..." for a word with possible suggestions
; empty line to indicate that the input was fully processed.
;
; Thats the basis, quite simple. Of course there are more commands and options.
; See the Aspell manual for that (http://aspell.sourceforge.net/), especially this page:
; http://aspell.sourceforge.net/man-html/Through-A-Pipe.html
;
; Ok, lets get started with the code, first just a few helper functions
; for coloring in the EditorGadget:
; ------------------------------------------------------------------------------------
; Selects Text inside an EditorGadget
; Line numbers range from 0 to CountGadgetItems(#Gadget)-1
; Char numbers range from 1 to the length of a line
; Set Line numbers to -1 to indicate the last line, and Char
; numbers to -1 to indicate the end of a line
; selecting from 0,1 to -1, -1 selects all.
Procedure Editor_Select(Gadget, LineStart.l, CharStart.l, LineEnd.l, CharEnd.l)
sel.CHARRANGE
sel\cpMin = SendMessage_(GadgetID(Gadget), #EM_LINEINDEX, LineStart, 0) + CharStart - 1
If LineEnd = -1
LineEnd = SendMessage_(GadgetID(Gadget), #EM_GETLINECOUNT, 0, 0)-1
EndIf
sel\cpMax = SendMessage_(GadgetID(Gadget), #EM_LINEINDEX, LineEnd, 0)
If CharEnd = -1
sel\cpMax + SendMessage_(GadgetID(Gadget), #EM_LINELENGTH, sel\cpMax, 0)
Else
sel\cpMax + CharEnd - 1
EndIf
SendMessage_(GadgetID(Gadget), #EM_EXSETSEL, 0, @sel)
EndProcedure
; Set the Text color for the Selection
; in RGB format
Procedure Editor_Color(Gadget, Color.l)
format.CHARFORMAT
format\cbSize = SizeOf(CHARFORMAT)
format\dwMask = #CFM_COLOR
format\crTextColor = Color
SendMessage_(GadgetID(Gadget), #EM_SETCHARFORMAT, #SCF_SELECTION, @format)
EndProcedure
; get line with the cursor
Procedure Editor_CursorLine(Gadget)
SendMessage_(GadgetID(Gadget), #EM_GETSEL, @selStart, 0)
ProcedureReturn SendMessage_(GadgetID(Gadget), #EM_LINEFROMCHAR, selStart, 0)
EndProcedure
; get the position of teh cursor in the line
Procedure Editor_CursorChar(Gadget)
SendMessage_(GadgetID(Gadget), #EM_GETSEL, @selStart, 0)
lineStart = SendMessage_(GadgetID(Gadget), #EM_LINEINDEX, SendMessage_(GadgetID(Gadget), #EM_LINEFROMCHAR, selStart, 0), 0)
ProcedureReturn selStart - lineStart + 1
EndProcedure
; ------------------------------------------------------------------------------------
#Window = 0
#Editor = 0
#Check = 1
#Suggest = 2
#LangText= 3
#Lang = 4
#LangSet = 5
; Request the Aspell executable (located in "bin" in the installation directory)
;
AspellExe$ = OpenFileRequester("Select Aspell.exe:", "Aspell.exe", "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*", 0)
;AspellExe$ = "C:\Program Files\Aspell\bin\aspell.exe"
If AspellExe$ = ""
End
EndIf
; Start the program. Read and Write flags are required of course to communicate
; We also read the error output, which is usefull for the language change below
; for example. "-a" starts the pipe mode.
;
Aspell = RunProgram(AspellExe$, "-a", "", #PB_Program_Hide|#PB_Program_Open|#PB_Program_Write|#PB_Program_Read|#PB_Program_Error)
If Aspell = 0
MessageRequester("Error", "Cannot executa Aspell.exe")
End
EndIf
; read the version string.
;
Version$ = ReadProgramString(Aspell)
If Version$ = ""
;
; if no version is given, it was probably an error, so read the error output
;
MessageRequester("Error:", ReadProgramError(Aspell))
CloseProgram(Aspell)
End
EndIf
; Aspell selects the language based on the locale setting.
; The "$$l" command will print one line with the choosen language as result)
; (see below on how To set a different language.)
;
WriteProgramStringN(Aspell, "$$l") ; write the command (the newline is important!)
Language$ = ReadProgramString(Aspell); read the result (will read one line of input)
; Open up a nice gui...
;
If OpenWindow(#Window, 0, 0, 450, 350, #PB_Window_SystemMenu|#PB_Window_ScreenCentered, "Spell correction made easy...")
CreateGadgetList(WindowID(#Window))
ButtonGadget(#Check, 5, 5, 120, 20, "Check Document")
ButtonGadget(#Suggest, 130, 5, 120, 20, "Suggest words")
TextGadget(#LangText, 255, 7, 90, 20, "Language:", #PB_Text_Right)
StringGadget(#Lang, 350, 5, 40, 20, Language$)
ButtonGadget(#LangSet, 395, 5, 50, 20, "Set")
EditorGadget(#Editor, 5, 30, 445, 310)
AddGadgetItem(#Editor, -1, "Version string: "+Version$)
AddGadgetItem(#Editor, -1, "Type something and then press the 'Check Document' button.")
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget
Select EventGadget()
Case #LangSet
;
; to select a new language, Aspell must be restarted with the --lang=<code>
; option. <code> should be the the language code like "en", "de", "fr", ...
;
; We first start the new program to see if all worked fine, so the old
; one can still be used if something went wrong
;
NewLanguage$ = Trim(GetGadgetText(#Lang))
NewAspell = RunProgram(AspellExe$, "-a --lang="+NewLanguage$, "", #PB_Program_Hide|#PB_Program_Open|#PB_Program_Write|#PB_Program_Read|#PB_Program_Error)
If NewAspell = 0
; cannot run the exe at all
;
MessageRequester("Error", "Cannot start Aspell.exe with new language!")
SetGadgetText(#Lang, Language$)
Else
Version$ = ReadProgramString(NewAspell)
If Version$ = ""
; again, no version line probably means an error
;
MessageRequester("Error:", ReadProgramError(NewAspell))
SetGadgetText(#Lang, Language$)
CloseProgram(NewAspell)
Else
; success. we now end the old Aspell with CloseProgram()
; NOTE: CloseProgram() does not kill the program, but since it closes
; its input, Aspell will end itself.
;
MessageRequester("Information:", "New Language set.")
CloseProgram(Aspell)
Aspell = NewAspell
EndIf
EndIf
Case #Check
; Now there is a general check for errors:
;
; First disable redrawing and remove all old colors
;
SendMessage_(GadgetID(#Editor), #WM_SETREDRAW, 0, 0)
Editor_Select(#Editor, 0, 1, -1, -1)
Editor_Color(#Editor, $000000)
; Now go line by line and write it to Aspell
lines = CountGadgetItems(#Editor)
For i = 0 To lines - 1
Text$ = GetGadgetItemText(#Editor, i, 0)
WriteProgramStringN(Aspell, "^"+Text$)
; Read the output until the empty line is reached.
; Possible starts of result lines
; * - correct word (ignored)
; # - wrong word
; & - wrong word with suggestions
;
; We are not intrested in suggestions here, so we just get
; offset and length of the word in both cases to mark the word red
;
Repeat
Result$ = ReadProgramString(Aspell)
If Left(Result$, 1) = "#"
Offset = Val(StringField(Result$, 3, " "))
Length = Len(StringField(Result$, 2, " "))
Editor_Select(#Editor, i, Offset, i, Offset+Length)
Editor_Color(#Editor, $0000FF)
ElseIf Left(Result$, 1) = "&"
Result$ = StringField(Result$, 1, ":") ; cut all the suggestions
Offset = LineStart + Val(StringField(Result$, 4, " "))
Length = Len(StringField(Result$, 2, " "))
Editor_Select(#Editor, i, Offset, i, Offset+Length)
Editor_Color(#Editor, $0000FF)
EndIf
Until Result$ = ""
Next i
; reset selection and redraw the gadget
;
Editor_Select(#Editor, 0, 1, 0, 1)
SendMessage_(GadgetID(#Editor), #WM_SETREDRAW, 1, 0)
InvalidateRect_(GadgetID(#Editor), 0, 0)
Case #Suggest
; Here we are looking for suggestions on a word under the cursor.
;
; First get the cursor position
;
Line = Editor_CursorLine(#Editor)
Cursor = Editor_CursorChar(#Editor)
Text$ = GetGadgetItemText(#Editor, Line, 0)
; isolate the word from the line
;
WordStart = Cursor
WordEnd = Cursor
While WordStart > 0 And FindString("ABCDEFGHIJKLMNOPQRSTUVWXYZ", UCase(Mid(Text$, WordStart, 1)), 1) <> 0
WordStart - 1
Wend
While WordEnd < Len(Text$) And FindString("ABCDEFGHIJKLMNOPQRSTUVWXYZ", UCase(Mid(Text$, WordEnd, 1)), 1) <> 0
WordEnd + 1
Wend
Word$ = Mid(Text$, WordStart+1, WordEnd-WordStart)
If Word$ <> ""
; Now once again, pass it to Aspell
;
WriteProgramStringN(Aspell, "^"+Word$)
; Always use a loop until an empty line is returned. To be sure all
; processing is done
;
Repeat
Result$ = ReadProgramString(Aspell)
If Left(Result$, 1) = "*" ; correct word
MessageRequester("Suggestions:", "This word is correct.")
ElseIf Left(Result$, 1) = "#" ; wrong word
MessageRequester("Suggestions:", "There are no suggestions for this word.")
ElseIf Left(Result$, 1) = "&" ; suggestions. they start after the ":"
Suggestions$ = StringField(Result$, 2, ":")
MessageRequester("Suggestions:", Suggestions$)
EndIf
Until Result$ = ""
EndIf
EndSelect
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
; Close Aspell before ending
;
CloseProgram(Aspell)
End