home *** CD-ROM | disk | FTP | other *** search
- { MSSPELL.PAS
- MS 4.0
- Copyright (c) 1985, 87 by Borland International, Inc. }
-
- {$I msdirect.inc}
-
- unit MsSpell;
- {-Spelling checker for MicroStar - uses Turbo Lightning}
-
- interface
-
- uses
- Crt, {Basic video operations - standard unit}
- Dos, {DOS interface - standard unit}
- Errors, {Runtime error handler}
- MsVars, {Global types and declarations}
- MsScrn1, {Fast screen writing routines}
- MsString, {String primitives}
- MsPtrOp, {Pointer primitives}
- EscSeq, {Returns text string for extended scan codes}
- MsCmds, {Maps keystrokes to commands}
- Int24, {DOS critical error handler}
- Message, {Message system}
- MsUser, {User keyboard input, line edit, error report, help}
- MsMemOp, {Text buffer allocation and deallocation}
- MsBack, {Background processes}
- MsScrn2, {Editor screen updating}
- MsMenu, {Pulldown and custom menu system}
- MsDir, {Popup directory picker}
- MsEdit, {Basic editing commands}
- MsFile; {File I/O routines}
-
- procedure EdSpellingCheck;
- {-Check spelling of block or file using Turbo Lightning}
-
- {==========================================================================}
-
- implementation
-
- const
- LightDictFileExt : ExtString = 'DIC';
- MarkStr : string[1] = '~'; {Marks unrecognized words during spelling check}
- LastHashBucket = 211; {PRIME number of entries in hash table}
- {Must match that in MSSPELL.ASM}
- LightChars : string[28] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'#39;
-
- type
-
- {Interface to Turbo Lightning}
- DITtype =
- record
- Block : Word; {Dictionary block number}
- WordNum : Word; {Intrablock word number}
- GlobalNum : array[0..2] of Byte; {Global Word number}
- MinGlobal : array[0..2] of Byte; {Min word number for range}
- MaxGlobal : array[0..2] of Byte; {Max word number for range}
- TokenLen : Word; {token length (word length)}
- RtokenLen : Word; {returned word token length}
- DisplayCount : Word; {Display count}
- FscPointer : Word; {offset of synonym area}
- MastDicOfs : Word; {offset of master dic index}
- OutDicOfs : Word; {offset of outboard dic index}
- UtokenOfs : Word; {offset of untranslated token}
- HotKeyOfs : Word; {offset of hot key area}
- EnvOfs : Word; {offset of environment area}
- RamFileOfs : Word; {offset of Ram Dictionary File name}
- MastFileOfs : Word; {offset of Disk Dictionary File name}
- AuxFileOfs : Word; {offset of Aux Dictionary File name}
- SynFileOfs : Word; {offset of Synonym Dictionary File name}
- MinMaxOfs : Word; {offset of Max, Min token len bytes}
- DictModeOfs : Word; {offset of Dictionary mode word}
- LikelyWordOfs : Word; {offset of likely word list}
- InsOvwOfs : Word; {offset of Insert/Overwrite byte}
- CurEnvOfs : Word; {offset of Current Environment pointer}
- RAMDictOfs : Word; {offset of RAM dictionary Index}
- AllIndexSeg : Word; {segment of all indices}
- end;
- DITPtrType = ^DITtype;
- HotKeyType = array[1..7] of Word;
- HotKeyPtrType = ^HotKeyType;
-
- {Corrective actions available when unrecognized word is found}
- SplActionType =
- (SplIgnore, {Ignore}
- SplAddLocal, {Add to local dictionary in RAM}
- SplChkLikely, {Check likely words via Lightning}
- SplEdit, {Edit the word on the fly}
- SplMark, {Mark in text}
- SplAddauxi, {Add to auxi dictionary}
- SplMarkRest, {Mark all in text without prompt}
- SplQuit {Quit checking}
- );
-
- {Support for RAM dictionary local to MicroStar}
- RamDictPtr = ^RamDictRec;
- WordPtr = ^VarString;
- RamDictRec =
- record
- Next : RamDictPtr; {Points to next hash table entry}
- Word : WordPtr; {Points to string}
- end;
- RamDictTable = array[0..LastHashBucket] of RamDictPtr;
-
- var
- DITPtr : DITPtrType; {Points to Lightning Data Interchange Table}
- HotKeyPtr : HotKeyPtrType; {Points to Lightning hot key table}
- SaveHotKeys : HotKeyType; {Saves Lightning interactive hot keys}
- SaveAutoProof : Boolean; {Saves Lightning interactive autoproof state}
- LastLikelyWordCount : Integer; {Number of soundalike words returned by Lightning}
- BadWord : VarString; {Most recent unknown word}
-
- {$L MSSPELL}
-
- function EdRamHash(var S) : Word; external;
- {-Given a string, return a Word between 0 and LastHashBucket}
-
- function EdInitLocalPtr : Pointer; external;
- {-Return a pointer to the start of the local dictionary}
-
- function EdEngine(Fcode, AlValue, CxValue, DxValue : Word; var AnyString) : Word;
- {-Call the Lightning engine}
- var
- regs : registers;
-
- begin {EdEngine}
- with regs do begin
- Al := lo(AlValue);
- Ah := $ED;
- Bh := $ED;
- Bl := lo(Fcode);
- Cx := CxValue;
- Dx := DxValue;
- Ds := Seg(AnyString);
- Si := Ofs(AnyString);
- intr($16, regs);
- EdEngine := ax;
- end;
- end; {EdEngine}
-
- function EdLightningPresent : Boolean;
- {-Find out if Lightning is in memory}
- var
- Junk : VarString;
-
- begin {EdLightningPresent}
- EdLightningPresent := (EdEngine(0, 0, 0, 0, Junk) = $5205);
- end; {EdLightningPresent}
-
- function EdLoadAuxDict(AuxName : Filepath) : Boolean;
- {-Load Lightning's auxiliary dictionary}
-
- begin {EdLoadAuxDict}
- AuxName[Succ(Length(AuxName))] := Null;
- EdLoadAuxDict := (EdEngine(4, 0, 0, 0, AuxName) <= 2);
- end; {EdLoadAuxDict}
-
- procedure EdReserveLightning(Reserve : Boolean; var AuxName : Filepath);
- {-Prepare or release Lightning for this application}
- var
- AuxAvailable, Junk : Boolean;
-
- function EdAutoProof(On : Boolean) : Boolean;
- {-Change the AutoProof mode and return the previous state}
- var
- NewState : Word;
- Junk : VarString;
-
- begin {EdAutoProof}
- if On then
- NewState := $FF
- else
- NewState := 0;
- EdAutoProof := (EdEngine(6, NewState, 0, 0, Junk) <> 0);
- end; {EdAutoProof}
-
- function EdDITAddress : DITPtrType;
- {-Return a pointer to the Lightning internal data structure}
- var
- Junk : VarString;
-
- begin {EdDITAddress}
- EdDITAddress := Ptr(EdEngine(2, 0, 0, 0, Junk), EdEngine(3, 0, 0, 0, Junk));
- end; {EdDITAddress}
-
- function EdGetAuxDictName : Filepath;
- {-Return the auxiliary dictionary file name from Lightning}
- type
- ASCIIZ = array[0..255] of Char;
- var
- AuxNamePtr : ^ASCIIZ;
- AuxName : Filepath;
- AuxLen : Byte absolute AuxName;
-
- begin {EdGetAuxDictName}
- {Point into the Lightning data interchange table}
- AuxNamePtr := Ptr(Seg(DITPtr^), DITPtr^.AuxFileOfs);
- {Convert ASCIIZ string to Turbo string}
- AuxLen := 0;
- while AuxNamePtr^[AuxLen] <> Null do
- Inc(AuxLen);
- Move(AuxNamePtr^, AuxName[1], AuxLen);
- {Add default extension}
- EdDefaultExtension(LightDictFileExt, AuxName);
- EdGetAuxDictName := AuxName;
- end; {EdGetAuxDictName}
-
- begin {EdReserveLightning}
-
- if Reserve then begin
-
- {Set up pointers to Lightning data structures}
- DITPtr := EdDITAddress;
- HotKeyPtr := Ptr(Seg(DITPtr^), DITPtr^.HotKeyOfs);
-
- {Save the current hot keys}
- SaveHotKeys := HotKeyPtr^;
-
- {Get the filename of the auxiliary dictionary}
- AuxName := EdGetAuxDictName;
-
- {Have Lightning load the auxiliary dictionary if available}
- AuxAvailable := EdLoadAuxDict(AuxName);
-
- {Disable the Lightning hot keys}
- FillChar(HotKeyPtr^, SizeOf(HotKeyType), $FF);
-
- {Turn auto proof mode off}
- SaveAutoProof := EdAutoProof(False);
-
- end else begin
-
- {Release Lightning for interactive use}
- Junk := EdAutoProof(SaveAutoProof);
- HotKeyPtr^ := SaveHotKeys;
-
- end;
- end; {EdReserveLightning}
-
- procedure EdInitEndPoints(var T : BlockMarker);
- {-Set window and end marker for the region to be spell checked}
- var
- W : Pwindesc;
- Rezoom : Boolean;
-
- begin {EdInitEndPoints}
- if EdNoBlock then begin
- {No marked block, check from cursor to end of document}
- with T do begin
- EdSetPtrNil(Line);
- Col := 0;
- end;
-
- end else begin
- {Block marked and visible, check just the block}
- T := Blockto;
- W := EdFindWindow(Blockfrom.Line);
- Rezoom := Zoomed and (W <> Curwin);
- if Rezoom then
- EdZoomWindow(False);
- Curwin := W;
- if Rezoom then
- EdZoomWindow(False);
- EdJumpMarker(Blockfrom);
-
- end;
-
- {Align cursor to start on a Lightning word boundary}
- with Curwin^ do begin
- {Back up beyond start of current word}
- while (Colno >= 1) and (Pos(Upcase(Curline^.Txt^[Colno]), LightChars) <> 0) do
- Dec(Colno);
- Inc(Colno);
- end;
- end; {EdInitEndPoints}
-
- function EdAddWord(var RamDict : RamDictTable; P : WordPtr) : Boolean;
- {-Add a word to the RAM dictionary, returning True if successful}
- var
- H : Word;
- Old : RamDictPtr;
-
- begin {EdAddWord}
- {Assure sufficient memory}
- if EdMemAvail(SizeOf(RamDictRec), FreeListPerm) then begin
- {Compute hash}
- H := EdRamHash(P^);
-
- {Add to hash table}
- Old := RamDict[H];
- GetMem(RamDict[H], SizeOf(RamDictRec));
- with RamDict[H]^ do begin
- Next := Old;
- Word := P;
- end;
- EdAddWord := True;
- end else
- EdAddWord := False;
- end; {EdAddWord}
-
- procedure EdSetWindowPos(var Xmin, Ymin : Integer; Width, Height : Integer);
- {-Return upper left corner of window such that window doesn't overwrite current position}
-
- begin {EdSetWindowPos}
- with Curwin^ do begin
- if Colno-Leftedge+Leftcol-(Length(BadWord) shr 1) <= (PhyScrCols shr 1) then
- {Left half of screen, put menu on right}
- Xmin := Succ(PhyScrCols-Width)
- else
- {Right half of screen}
- Xmin := 1;
-
- if Pred(Firsttextno+Lineno) <= (PhyscrRows shr 1) then
- {Top half of screen, put menu on bottom}
- Ymin := Succ(PhyscrRows-Height)
- else
- {Bottom half of screen}
- Ymin := LogtopScr;
- end;
- end; {EdSetWindowPos}
-
- function EdPickLikelyWord(ScanDict : Boolean) : VarString;
- {-Display a menu and return a likely word}
- const
- WordsPerPage = 12;
- var
- Wid, Cnt, Num, Row, Lines, Xmin, Ymin : Integer;
- Ch : Char;
- Quitting : Boolean;
- W : WindowRec;
- Title : VarString;
-
- function EdLikelyWordCount : Word;
- {-Return the number of likely substitutes for the last word checked}
- var
- Junk : VarString;
-
- begin {EdLikelyWordCount}
- EdLikelyWordCount := EdEngine($F, 0, 0, 0, Junk);
- end; {EdLikelyWordCount}
-
- function EdGetLikelyWord(N : Word) : VarString;
- {-Return the n'th likely word}
- var
- S, O, I : Word;
- P : ^VarString;
-
- begin {EdGetLikelyWord}
- S := Seg(DITPtr^);
- O := DITPtr^.LikelyWordOfs;
- for I := 1 to N do begin
- P := Ptr(S, O);
- O := O+Succ(Ord(P^[0]));
- end;
- EdGetLikelyWord := P^;
- end; {EdGetLikelyWord}
-
- function EdMaxLikelyWordWidth(Cnt : Integer) : Integer;
- {-Return the maximum word length}
- var
- Max, I : Integer;
- W : VarString;
-
- begin {EdMaxLikelyWordWidth}
- Max := 0;
- for I := 1 to Cnt do begin
- W := EdGetLikelyWord(I);
- if Length(W) > Max then
- Max := Length(W);
- end;
- EdMaxLikelyWordWidth := Max;
- end; {EdMaxLikelyWordWidth}
-
- procedure EdWriteEntry(Num : Integer; Row, Attr : Byte);
- {-Write one word to the screen}
-
- begin {EdWriteEntry}
- with W do
- EdFastWrite(EdPadEntry(EdGetLikelyWord(Num), XSize-2), YPosn+Row, Succ(XPosn), Attr);
- end; {EdWriteEntry}
-
- procedure EdDrawFullPage(Num, Lines : Integer);
- {-Draw one full window full of entries, starting at entry num}
- var
- I : Integer;
-
- begin {EdDrawFullPage}
- for I := 1 to Lines do
- EdWriteEntry(Pred(Num+I), I, ScreenAttr[MnColor]);
- end; {EdDrawFullPage}
-
- begin {EdPickLikelyWord}
-
- if ScanDict then begin
- EdWritePromptLine(EdGetMessage(281));
- Cnt := EdLikelyWordCount;
- LastLikelyWordCount := Cnt;
- end else
- Cnt := LastLikelyWordCount;
-
- if Cnt <= 0 then begin
- EdDisplayPromptWindow(
- EdGetMessage(280)+'-'+EdGetMessage(305), 13, [#27], Ch, NormalBox);
- EdPickLikelyWord := '';
- Exit;
- end;
-
- EdWritePromptLine(EdGetMessage(304));
-
- {Get max width of likely candidates}
- Wid := EdMaxLikelyWordWidth(Cnt);
- if Wid < 16 then
- Wid := 16;
-
- if Cnt > WordsPerPage then
- Lines := WordsPerPage
- else
- Lines := Cnt;
-
- {See where window should go to avoid overwriting word}
- EdSetWindowPos(Xmin, Ymin, Wid+4, Lines+2);
-
- {Put up a window}
- EdSaveTextWindow(Border, EdGetMessage(279), Xmin, Ymin, Xmin+Wid+3, Succ(Ymin+Lines), W);
-
- if Cnt > WordsPerPage then
- {Indicate that there are more entries}
- with W do begin
- Title := EdGetMessage(263);
- EdFastWrite(Title, Pred(YPosn+YSize), XPosn+XSize-14, ScreenAttr[MfColor]);
- end;
-
- Num := 1;
- Row := 1;
- EdDrawFullPage(Num, Lines);
- Quitting := False;
-
- repeat
-
- EdWriteEntry(Num, Row, ScreenAttr[MsColor]);
- if Cnt > WordsPerPage then
- {Indicate that other entries are off ends of menus}
- with W do begin
- if Num > Row then
- {More words are above top of window}
- Ch := ^X
- else
- Ch := Blank;
- EdFastWrite(Ch, Pred(YPosn+YSize), XPosn+XSize-13, ScreenAttr[MfColor]);
- if Num < Cnt+Row-Lines then
- {More words are below bottom of window}
- Ch := ^Y
- else
- Ch := Blank;
- EdFastWrite(Ch, Pred(YPosn+YSize), XPosn+XSize-12, ScreenAttr[MfColor]);
- end;
-
- case EdGetCursorCommand(DirCmdSet) of
-
- ^M : {Select}
- Quitting := True;
-
- ^[ : {Escape}
- begin
- Num := 0;
- Quitting := True;
- end;
-
- ^E : {Scroll up}
- if Num > 1 then begin
- EdWriteEntry(Num, Row, ScreenAttr[MnColor]);
- Dec(Num);
- if Row = 1 then begin
- GoToXY(1, 1);
- InsLine;
- end else
- Dec(Row);
- end else if Lines >= Cnt then begin
- {Wrap to end}
- Num := Cnt;
- Row := Cnt;
- EdDrawFullPage(Succ(Num-Row), Lines);
- end;
-
- ^X : {Scroll down}
- if Num < Cnt then begin
- EdWriteEntry(Num, Row, ScreenAttr[MnColor]);
- Inc(Num);
- if Row >= Lines then begin
- GoToXY(1, 1);
- DelLine;
- Row := Lines;
- end else
- Inc(Row);
- end else if Lines >= Cnt then begin
- {Wrap to begin}
- Num := 1;
- Row := 1;
- EdDrawFullPage(Num, Lines);
- end;
-
- ^R : {Page up}
- if Num > 1 then begin
- Num := Num-Lines;
- if Num < 1 then
- Num := 1;
- Row := 1;
- EdDrawFullPage(Num, Lines);
- end;
-
- ^C : {Page down}
- if Num < Cnt then begin
- Num := Num+Lines;
- if Num > Cnt then
- Num := Cnt;
- Row := Lines;
- if Row > Cnt then
- Row := Cnt;
- EdDrawFullPage(Succ(Num-Row), Lines);
- end;
-
- ^T : {Top of list}
- if Num > 1 then begin
- Num := 1;
- Row := 1;
- EdDrawFullPage(Num, Lines);
- end;
-
- ^B : {Bottom of list}
- if Num < Cnt then begin
- Num := Cnt;
- if Cnt < Lines then
- Row := Cnt
- else
- Row := Lines;
- EdDrawFullPage(Succ(Num-Row), Lines);
- end;
-
- end;
- until Abortcmd or Quitting;
-
- {Return the new word, empty string if none}
- if Abortcmd or (Num = 0) then
- EdPickLikelyWord := ''
- else
- EdPickLikelyWord := EdGetLikelyWord(Num);
-
- {Restore screen}
- EdRestoreTextWindow(W);
- EdWritePromptLine(EdGetMessage(278));
- EdSetCursor(CursorOff);
-
- end; {EdPickLikelyWord}
-
- function EdGetFixAction : SplActionType;
- {-Prompt for a fix type}
- const
- MaxChoices = 7;
- var
- Menu : CustomMenuRec;
- CalcXmin, CalcYmin, Maxlen, Choice : Integer;
-
- function EdBuildMessages(var Menu : CustomMenuRec; var Maxlen : Integer) : Boolean;
- {-Build the message table for the menu}
- var
- Item : Integer;
- S : VarString;
-
- begin {EdBuildMessages}
- EdBuildMessages := False;
- with Menu do begin
-
- if EdMemAvail(Succ(MaxChoice) shl 2, FreeListTemp) then
- {Get the pointers}
- GetMem(Messages, Succ(MaxChoice) shl 2)
- else
- Exit;
-
- Maxlen := 0;
-
- {Get the string space and fill in the strings}
- for Item := MinChoice to MaxChoice do begin
- S := EdGetMessage(263+Item);
- if Length(S) > Maxlen then
- Maxlen := Length(S);
- if EdMemAvail(Succ(Length(S)), FreeListTemp) then
- GetMem(Messages^[Item], Succ(Length(S)))
- else
- Exit;
- Messages^[Item]^ := S;
- end;
- end;
- EdBuildMessages := True;
- end; {EdBuildMessages}
-
- begin {EdGetFixAction}
-
- {Initialize the menu}
- with Menu do begin
- MessageNum := 257;
- PromptNum := 277;
- MinChoice := 1;
- MaxChoice := MaxChoices;
- InitChoice := 1;
- CmdSet := PrtCmdSet;
- UseLetters := True;
- end;
- if not(EdBuildMessages(Menu, Maxlen)) then begin
- EdErrormsg(35);
- Exit;
- end;
-
- {See where window should go to avoid overwriting word}
- EdSetWindowPos(CalcXmin, CalcYmin, Maxlen+4, MaxChoices+2);
- with Menu do begin
- Xmin := CalcXmin;
- Ymin := CalcYmin;
- end;
-
- {Get the menu choice}
- EdGetCustomMenuChoice(Menu, Choice);
-
- if not(Abortcmd) then
- EdGetFixAction := SplActionType(Pred(Choice));
-
- EdWritePromptLine(EdGetMessage(278));
-
- end; {EdGetFixAction}
-
- procedure EdAddAuxiDict(W : VarString; AuxName : Filepath);
- {-Add a word to the auxiliary dictionary}
- label
- ExitPoint;
- const
- MaxChoices = 4;
- var
- AuxFile : Text;
- Choice, CalcXmin, CalcYmin : Integer;
- Menu : CustomMenuRec;
-
- function EdBuildMessages(var Menu : CustomMenuRec) : Boolean;
- {-Build the message table for the menu}
- var
- Item : Integer;
- S : VarString;
-
- begin {EdBuildMessages}
- EdBuildMessages := False;
- with Menu do begin
-
- if EdMemAvail(Succ(MaxChoice) shl 2, FreeListTemp) then
- {Get the pointers}
- GetMem(Messages, Succ(MaxChoice) shl 2)
- else
- Exit;
-
- {Get the string space and fill in the strings}
- for Item := MinChoice to MaxChoice do begin
- S := EdGetMessage(258+Item);
- if EdMemAvail(Succ(Length(S)), FreeListTemp) then
- GetMem(Messages^[Item], Succ(Length(S)))
- else
- Exit;
- Messages^[Item]^ := S;
- end;
- end;
- EdBuildMessages := True;
- end; {EdBuildMessages}
-
- begin {EdAddAuxiDict}
-
- {See where window should go to avoid overwriting word}
- EdSetWindowPos(CalcXmin, CalcYmin, 30, MaxChoices+2);
-
- {Initialize the menu}
- with Menu do begin
- Xmin := CalcXmin;
- Ymin := CalcYmin;
- MessageNum := 271;
- PromptNum := 276;
- MinChoice := 1;
- MaxChoice := MaxChoices;
- InitChoice := 1;
- CmdSet := PrtCmdSet;
- UseLetters := True;
- end;
- if not(EdBuildMessages(Menu)) then begin
- EdErrormsg(35);
- goto ExitPoint;
- end;
-
- {Get the menu choice}
- EdGetCustomMenuChoice(Menu, Choice);
-
- if Abortcmd then
- goto ExitPoint;
-
- {Modify word based on choice}
- case Choice of
- 1 : {Add in lower case}
- EdLocase(W);
-
- 2 : {First capitalized, rest lowercase}
- begin
- EdLocase(W);
- W[1] := Upcase(W[1]);
- end;
-
- 3 : {All uppercase}
- EdUpcase(W);
- end;
-
- {Add to dictionary file}
- if EdExistFile(AuxName) then begin
- Assign(AuxFile, AuxName);
- Append(AuxFile);
- if EdFileerror then begin
- {Force return to main spelling menu}
- Abortcmd := True;
- goto ExitPoint;
- end;
- end else begin
- EdErrormsg(58);
- {Force return to main spelling menu}
- Abortcmd := True;
- goto ExitPoint;
- end;
-
- WriteLn(AuxFile, W);
- Write(AuxFile, ^Z);
- if EdFileerror then begin
- {Force return to main spelling menu}
- Abortcmd := True;
- goto ExitPoint;
- end;
- Close(AuxFile);
- if EdFileerror then begin
- {Force return to main spelling menu}
- Abortcmd := True;
- goto ExitPoint;
- end;
-
- {Reload Auxi dictionary}
- if not(EdLoadAuxDict(AuxName)) then begin
- {Unable to reload it}
- EdErrormsg(74);
- Abortcmd := True;
- end;
-
- ExitPoint:
- EdWritePromptLine(EdGetMessage(278));
-
- end; {EdAddAuxiDict}
-
- procedure EdSpellingCheck;
- {-Check spelling of block or file using Turbo Lightning}
- var
- Marking, Junk, SaveCursor : Boolean;
- AuxName : Filepath;
- RamDict : RamDictTable;
- Action : SplActionType;
- CheckTo : BlockMarker;
-
- procedure EdCheckWords(CheckTo : BlockMarker);
- {-Scan the text stream and check words}
- const
- LastCh : Char = ' '; {Previous character in line}
- var
- Done : Boolean;
- W, NewWord : VarString;
- Ch : Char;
- Wptr : WordPtr;
-
- procedure EdGetNextWord(var Done : Boolean; var W : VarString);
- {-Return the next word in the text, set Done when no more to go}
- var
- StartCol, Len, WlenInt : Integer;
- GotStart : Boolean;
- Ch : Char;
-
- begin {EdGetNextWord}
- with Curwin^, CheckTo do begin
-
- Len := Curline^.Bufflen;
-
- repeat
-
- {Done when past the CheckTo marker}
- Done := (Curline = Line) and (Colno >= Col);
-
- {Get next line if previous one exhausted}
- while not(Done) and (Colno > Len) do begin
- {Move to next line}
- if EdPtrIsNil(Curline^.Fwdlink) then
- Done := True
- else begin
- EdFwdPtr(Curline);
- if Lineno > (Lastlineno-Firsttextno) shr 1 then
- {Keep current line roughly centered in window}
- EdFwdPtr(TopLine)
- else
- Inc(Lineno);
- Colno := 1;
- Inc(Clineno);
- {Approximation of crelpos for display here}
- Crelpos := (LongInt(1000)*LongInt(Clineno)) div LongInt(TlineNo);
- {Have we passed the end point?}
- Done := (Curline = Line) and (Colno >= Col);
- end;
- if not(Done) then begin
- Len := Curline^.Bufflen;
- LastCh := Blank;
- end;
- end;
-
- GotStart := False;
- if not(Done) then
- with Curline^ do
- {Scan to next word starting point}
- while (Colno <= Len) and not(GotStart) do begin
- Ch := Upcase(Txt^[Colno]);
- if (Pos(LastCh, LightChars) = 0) then
- GotStart := (Pos(Ch, LightChars) <> 0);
- LastCh := Ch;
- Inc(Colno);
- end;
-
- until Done or GotStart;
-
- if GotStart then
- with Curline^ do begin
- {Store start position}
- StartCol := Pred(Colno);
- {Find end of word}
- Ch := Upcase(Txt^[Colno]);
- while (Colno <= Len) and
- ((Pos(Ch, LightChars) <> 0) or ((Ch = '-') and (Colno < Len) and not(Txt^[Succ(Colno)] = '-')))
- do begin
- Inc(Colno);
- Ch := Upcase(Txt^[Colno]);
- end;
- {Store string}
- if Colno > StartCol then begin
- WlenInt := Colno-StartCol;
- if WlenInt > 32 then
- WlenInt := 32;
- W[0] := Chr(WlenInt);
- Move(Txt^[StartCol], W[1], Length(W));
- end;
- end;
- end;
-
- end; {EdGetNextWord}
-
- function EdInLocalDict(var RamDict : RamDictTable; W : VarString) : Boolean;
- {-Return true if word is in local RAM dictionary}
- var
- P : RamDictPtr;
-
- begin {EdInLocalDict}
-
- {Map the word into lower case as used by the dictionary}
- EdLocase(W);
-
- {Compute start of hash list}
- P := RamDict[EdRamHash(W)];
-
- while EdPtrNotNil(P) do
- if P^.Word^ = W then begin
- {Found it, get out now}
- EdInLocalDict := True;
- Exit;
- end else
- P := P^.Next;
-
- EdInLocalDict := False;
- end; {EdInLocalDict}
-
- function EdWordInDict(var RamDict : RamDictTable; var Word : VarString) : Boolean;
- {-See if word is in dictionary}
-
- begin {EdWordInDict}
- if Length(Word) = 1 then
- {All single characters are legal words}
- EdWordInDict := True
- else if EdInLocalDict(RamDict, Word) then
- {in local RAM dictionary}
- EdWordInDict := True
- else if EdEngine($E, 0, 0, 0, Word) <> 1 then
- {in Lightning RAM or Auxi dictionary}
- EdWordInDict := True
- else
- {check Lightning disk dictionary}
- EdWordInDict := (EdEngine(1, 0, 0, 0, Word) = 0);
- end; {EdWordInDict}
-
- function EdInsertRoom(P : PlineDesc; Start, Num : Integer) : Boolean;
- {-Insert num spaces at position start of line p, returning True if successful}
- var
- Len, NewLen : Integer;
-
- begin {EdInsertRoom}
-
- Len := EdTextLength(P);
- if Start > Len then
- NewLen := Succ(Start+Num)
- else
- NewLen := Succ(Len+Num);
-
- {Size up the line}
- if not EdSizeline(P, NewLen, True) then begin
- EdInsertRoom := False;
- Exit;
- end;
-
- {Move the text over}
- with P^ do
- if Start <= Len then
- Move(Txt^[Start], Txt^[Start+Num], Succ(Len-Start));
-
- {Fix up markers}
- EdFixMarkInsertedSpace(P, Start, Num);
- EdFixBlockInsertedSpace(P, Start, Num);
-
- EdInsertRoom := True;
-
- end; {EdInsertRoom}
-
- procedure EdInsertFix(Wlen : Integer; NewWord : VarString);
- {-Delete old word, insert new one}
- var
- Start : Integer;
-
- begin {EdInsertFix}
- with Curwin^ do begin
- Start := Colno-Wlen;
- {Remove the existing word}
- while Colno > Start do
- EdDeleteLeftChar;
- {Insert space in line for the fix}
- if EdInsertRoom(Curline, Start, Length(NewWord)) then begin
- {Move the fix into place}
- Move(NewWord[1], Curline^.Txt^[Start], Length(NewWord));
- {Leave the cursor at the start of the new word so it is rechecked}
- LastCh := Blank;
- Modified := True;
- end;
- end;
- end; {EdInsertFix}
-
- procedure EdInsertMark(Wlen : Integer);
- {-Insert editing mark noting where problems are}
- var
- Start : Integer;
-
- begin {EdInsertMark}
- with Curwin^ do begin
- Start := Colno-Wlen;
- {Insert space in line for mark}
- if EdInsertRoom(Curline, Start, Length(MarkStr)) then begin
- {Move the mark into place}
- Move(MarkStr[1], Curline^.Txt^[Start], Length(MarkStr));
- Colno := Colno+Length(MarkStr);
- Modified := True;
- end;
- end;
- end; {EdInsertMark}
-
- begin {EdCheckWords}
-
- with Curwin^ do begin
-
- {Initialize for first word}
- Done := False;
- Marking := False;
- if Colno = 1 then
- LastCh := Blank
- else
- LastCh := Curline^.Txt^[Pred(Colno)];
-
- {Assure line and column counts up to date}
- EdGenLineOne(Curwin);
-
- {Update the screen}
- EdUpdatewindow(Curwin);
- EdWritePromptLine(EdGetMessage(278));
-
- {Loop checking every word}
- repeat
-
- EdGetNextWord(Done, W);
-
- if EdKeyInterrupt then begin
- {Should we stop checking?}
- {Clear keyboard buffer}
- while EdKeyInterrupt do
- Ch := EdGetAnyChar;
- Done := EdYesNo(EdGetMessage(275));
- if Done then
- Abortcmd := True
- else begin
- EdSetCursor(CursorOff);
- if Marking then
- EdWritePromptLine(EdGetMessage(274))
- else
- EdWritePromptLine(EdGetMessage(278));
- Abortcmd := False;
- end;
- end;
-
- if not(Done) then begin
-
- {Show some screen action while checking}
- EdUpdateStatusLine(Curwin);
-
- {See if word in dictionary}
- if not(EdWordInDict(RamDict, W)) then begin
-
- if Marking then
-
- {Non-interactive, insert mark into text stream}
- EdInsertMark(Length(W))
-
- else begin
-
- {Put the bad word in a global for access by other routines}
- BadWord := W;
- {Show the current line with the error highlighted}
- EdHighlightScreen(Colno-Length(W), Pred(Colno), ScreenAttr[CursorColor], False);
- {Restore Lightning for interactive use during course of prompting}
- EdReserveLightning(False, AuxName);
-
- repeat
-
- Action := EdGetFixAction;
- if Abortcmd then begin
-
- {Quit checking}
- Done := True;
- Action := SplQuit;
-
- end else
- case Action of
-
- SplIgnore : {Ignore once}
- ;
-
- SplAddLocal : {Add to local dictionary in RAM}
- if EdMemAvail(Succ(Length(W)), FreeListTemp) then begin
- EdLocase(W);
- GetMem(Wptr, Succ(Length(W)));
- Move(W, Wptr^, Succ(Length(W)));
- if EdAddWord(RamDict, Wptr) then
- ;
- end else
- EdErrormsg(35);
-
- SplMark : {Mark in text}
- begin
- EdInsertMark(Length(W));
- EdUpdateScreen;
- end;
-
- SplMarkRest : {Mark remaining words in text without prompt}
- begin
- EdInsertMark(Length(W));
- EdWritePromptLine(EdGetMessage(274));
- Marking := True;
- end;
-
- SplChkLikely : {Check likely alternatives}
- begin
- {Assure the Lightning data area is correctly initialized}
- Junk := EdWordInDict(RamDict, W);
- {Choose from soundalike words}
- NewWord := EdPickLikelyWord(True);
- if Abortcmd or EdStringEmpty(NewWord) then
- {Loop around to try again}
- Abortcmd := False
- else begin
- EdInsertFix(Length(W), NewWord);
- EdUpdateScreen;
- {Go on}
- Action := SplIgnore;
- end;
- end;
-
- SplEdit : {Edit the word}
- begin
- EdWritePromptLine(EdGetMessage(273));
- NewWord := W;
- EdAskfor(EdGetMessage(272), 10, 17, 60, NewWord);
- if Abortcmd then begin
- {Give another chance}
- Action := SplChkLikely;
- Abortcmd := False;
- end else begin
- EdInsertFix(Length(W), NewWord);
- EdUpdateScreen;
- end;
- EdWritePromptLine(EdGetMessage(278));
- end;
-
- SplAddauxi : {Add to auxi dictionary}
- begin
- EdAddAuxiDict(W, AuxName);
- if Abortcmd then begin
- {Give another chance}
- Action := SplChkLikely;
- Abortcmd := False;
- end;
- end;
-
- end;
-
- EdSetCursor(CursorOff);
-
- until Action <> SplChkLikely;
-
- {Reserve Lightning again}
- EdReserveLightning(True, AuxName);
-
- end;
- end;
- end;
- until Done;
-
- end;
-
- {Assure cursor not past end of line}
- EdMoveCursorIntoLine;
-
- end; {EdCheckWords}
-
- procedure EdInitLocalDict(var RamDict : RamDictTable);
- {-Load a dictionary of most commonly used words for fastest checking}
- type
- DictBuffer = array[1..MaxInt] of Byte;
- var
- LocalPtr : ^DictBuffer;
- I, LocalPos : Integer;
- Wptr : WordPtr;
-
- begin {EdInitLocalDict}
-
- {Clear the hash table}
- for I := 0 to LastHashBucket do
- EdSetPtrNil(RamDict[I]);
-
- {Get pointer to start of local dictionary string table}
- LocalPtr := EdInitLocalPtr;
- LocalPos := 1;
-
- {Add words to RAM dictionary as long as space remains}
- repeat
-
- {Point to next string from local buffer}
- Wptr := Addr(LocalPtr^[LocalPos]);
-
- {Add word to the local dictionary}
- if not(EdAddWord(RamDict, Wptr)) then
- {Out of heap space}
- Exit;
-
- LocalPos := LocalPos+Succ(LocalPtr^[LocalPos]);
-
- until (LocalPtr^[LocalPos] = 0);
-
- end; {EdInitLocalDict}
-
- procedure EdDisposeLocalDict(var RamDict : RamDictTable);
- {-Release heap space used by local dictionary}
- var
- I : Integer;
- P, N : RamDictPtr;
-
- begin {EdDisposeLocalDict}
- for I := 0 to LastHashBucket do begin
- P := RamDict[I];
- while EdPtrNotNil(P) do begin
- N := P^.Next;
- if Seg(P^.Word^) <> CSeg then
- {Deallocate space for words just added to local dictionary}
- FreeMem(P^.Word, Succ(Length(P^.Word^)));
- {Deallocate space for the hash table record}
- FreeMem(P, SizeOf(RamDictRec));
- P := N;
- end;
- end;
- end; {EdDisposeLocalDict}
-
- begin {EdSpellingCheck}
-
- {Assure Lightning is installed}
- if not(EdLightningPresent) then begin
- EdErrormsg(57);
- Exit;
- end;
-
- {Clear menus from screen}
- if EdPtrNotNil(CurrMenu) then
- EdEraseMenus;
-
- {Set up screen}
- SaveCursor := SolidCursor;
- SolidCursor := False;
- EdSetCursor(CursorOff);
- EdEraseMenuHelp;
- EdWritePromptLine(EdGetMessage(258));
-
- {Initialize and dedicate Lightning for this program}
- EdReserveLightning(True, AuxName);
-
- {Initialize fast local dictionary}
- EdInitLocalDict(RamDict);
-
- {One last chance to get out in case of mistake}
- if EdKeyInterrupt then
- Abortcmd := True
- else begin
- {Get the start and stop points in the text stream}
- EdInitEndPoints(CheckTo);
- {Check the text}
- EdCheckWords(CheckTo);
- end;
-
- {Restore Lightning for interactive use}
- EdReserveLightning(False, AuxName);
-
- {Remove the local dictionary from memory}
- EdDisposeLocalDict(RamDict);
-
- {Restore screen}
- SolidCursor := SaveCursor;
- EdSetCursor(CursorType);
- EdSetCursorOff;
-
- if not(Abortcmd) then begin
- {Display completion status and wait for keypress}
- EdWritePromptLine(EdGetMessage(246));
- EdUpdateCursor;
- EdUpdateScreen;
- EdWaitforKey;
- end;
-
- end; {EdSpellingCheck}
-
-
- end.