www.pudn.com > tp60src.zip > HELPSCRN.PAS
unit HelpScrn;
{$O+,F+,S-,X+}
interface
uses Objects, HelpUtil;
type
PHelpScreen = ^THelpScreen;
THelpScreen = object(TObject)
MaxIndex: Word;
MaxRow: Word;
HasExample: Boolean;
Buffer: PChar;
BufSize: Word;
constructor Init(ABuffer: PChar; ABufSize: Word);
function Read(Index: Word): Boolean; virtual;
procedure GetRow(Row: Word; var Text: PChar; var Index: Word;
var Example: Boolean); virtual;
function Format(Width: Word; var P; N: Word): Boolean; virtual;
procedure GetPos(Index: Word; var Row, Col: Integer; var Len: Word); virtual;
function GetIndex(var S: string; var Len: Word): Word; virtual;
function GetContext(Index: Word): Integer; virtual;
procedure GetExample(var StartPos, EndPos: TPos); virtual;
function SearchRow(Row: Word): Integer;
function SearchIndex(Index: Word): Integer;
end;
PHelpIndex = ^THelpIndex;
THelpIndex = object(THelpScreen)
BufPtr: PChar;
CurIndex: Word;
ContextNumber: Word;
IndexToken: string[38];
CurLetter: Word;
function Read(Index: Word): Boolean; virtual;
procedure GetRow(Row: Word; var Text: PChar; var Index: Word;
var Example: Boolean); virtual;
function Format(Width: Word; var P; N: Word): Boolean; virtual;
procedure GetPos(Index: Word; var Row, Col: Integer; var Len: Word); virtual;
function GetIndex(var S: string; var Len: Word): Word; virtual;
function GetContext(Index: Word): Integer; virtual;
procedure GetExample(var StartPos, EndPos: TPos); virtual;
function GetToken: Word;
function TokenLength: Word;
procedure ReadLetter(Letter: Word);
procedure Track(Start, Target: Word);
procedure PositionTo(Index: Word);
procedure Parse;
end;
PHelpTopic = ^THelpTopic;
THelpTopic = object(THelpScreen)
TopicSize: Word;
BufPtr: PChar;
CurRow: Word;
CurIndex: Word;
InExample: Boolean;
constructor Init(ABuffer: PChar; ABufSize: Word);
function Read(Index: Word): Boolean; virtual;
procedure GetRow(Row: Word; var Text: PChar; var Index: Word;
var Example: Boolean); virtual;
function Format(Width: Word; var P; N: Word): Boolean; virtual;
procedure GetPos(Index: Word; var Row, Col: Integer; var Len: Word); virtual;
function GetIndex(var S: string; var Len: Word): Word; virtual;
function GetContext(Index: Word): Integer; virtual;
procedure GetExample(var StartPos, EndPos: TPos); virtual;
procedure CountRows;
procedure FindExample;
procedure Reset;
procedure GoBack(Amount: Word);
procedure GoForward(Amount: Word);
procedure GoRow(Row: Word);
procedure FindPos(Ofs: Word; var P: TPos);
function FindChar(Num: Integer; C: Char): Word;
end;
implementation
uses HelpFile;
type
PPosArray = ^TPosArray;
TPosArray = array[1..MaxCollectionSize] of ^TPos;
const
ColumnCount: Word = 0;
ColumnWidth: Word = 0;
Master: array[0..26] of record
Offset, Size, StartIndex, StartRow: Word
end = ((), (), (), (), (), (), (), (),
(), (), (), (), (), (), (), (),
(), (), (), (), (), (), (), (),
(),(),());
SaveMaxRow: Word = 0;
procedure SortPos(A: PPosArray; N: Word);
var
I, J: Word;
P: ^TPos;
begin
if N > 1 then
for I := 1 to N - 1 do
for J := I + 1 to N do
if (A^[I]^.Row > A^[J]^.Row) or
(A^[I]^.Row = A^[J]^.Row) and (A^[I]^.Col > A^[J]^.Col) then
begin
P := A^[I];
A^[I] := A^[J];
A^[J] := P
end;
end;
constructor THelpScreen.Init(ABuffer: PChar; ABufSize: Word);
begin
TObject.Init;
Buffer := ABuffer;
BufSize := ABufSize;
MaxIndex := 0;
end;
function THelpScreen.Read(Index: Word): Boolean;
begin
end;
procedure THelpScreen.GetRow(Row: Word; var Text: PChar; var Index: Word;
var Example: Boolean);
const
Empty: Char = #0;
begin
if Row >= MaxRow then
begin
Text := @Empty;
Index := MaxIndex;
Example := False;
end;
end;
function THelpScreen.Format(Width: Word; var P; N: Word): Boolean;
begin
Abstract;
end;
procedure THelpScreen.GetPos(Index: Word; var Row, Col: Integer; var Len: Word);
begin
Abstract;
end;
function THelpScreen.GetIndex(var S: string; var Len: Word): Word;
begin
Abstract;
end;
function THelpScreen.GetContext(Index: Word): Integer;
begin
Abstract;
end;
procedure THelpScreen.GetExample(var StartPos, EndPos: TPos);
begin
StartPos.Clear;
EndPos.Clear;
end;
function LetterNum(C: Char): Word;
var
I: Integer;
begin
I := Ord(UpCase(C)) - Ord('A') + 1;
if (I < 1) or (I > 26) then
I := 0;
LetterNum := I;
end;
function THelpScreen.SearchRow(Row: Word): Integer;
var
I, J, K: Integer;
Found: Boolean;
begin
if Row = 0 then
SearchRow := -1
else
begin
I := 0;
J := 26;
Found := False;
repeat
K := (J + I) shr 1;
if Master[K].StartRow > Row then
J := K - 1
else if (K < 26) and (Master[K+1].StartRow <= Row) then
I := K + 1
else
Found := True;
until Found;
SearchRow := K;
end;
end;
function THelpScreen.SearchIndex(Index: Word): Integer;
var
I, J, K: Integer;
Found: Boolean;
begin
I := 0;
J := 26;
Found := False;
repeat
K := (J + I) shr 1;
if Master[K].StartIndex > Index then
J := K - 1
else if (K < 26) and (Master[K+1].StartIndex <= Index) then
I := K + 1
else
Found := True;
until Found;
SearchIndex := K;
end;
function THelpIndex.GetToken: Word; assembler;
asm
PUSH DS
CLD
LDS SI,Self
MOV AX,[SI].CurIndex
CMP AX,[SI].MaxIndex
JB @@1
SUB AX,AX
JMP @@2
@@1: INC [SI].CurIndex
MOV AX,DS
MOV ES,AX
LEA DI,[SI].IndexToken+1
MOV DX,DI
LDS SI,[SI].BufPtr
SUB AH,AH
LODSB
MOV CX,AX
AND CL,1FH
SHR AL,1
SHR AL,1
SHR AL,1
SHR AL,1
SHR AL,1
ADD DI,AX
REP MOVSB
LODSW
LDS BX,Self
MOV [BX].ContextNumber,AX
MOV [BX].BufPtr.Word[0],SI
XCHG AX,DI
SUB AX,DX
MOV [BX].IndexToken.Byte,AL
@@2: POP DS
end;
function THelpIndex.TokenLength: Word; assembler;
asm
PUSH DS
CLD
LDS SI,Self
LDS SI,[SI].BufPtr
SUB AH,AH
LODSB
MOV BX,AX
AND BL,1FH
MOV CL,5
SHR AL,CL
ADD AX,BX
POP DS
end;
procedure THelpIndex.ReadLetter(Letter: Word);
begin
if Letter <> CurLetter then
with Master[Letter] do
begin
ReadIndex(Buffer, Offset, Size);
CurIndex := StartIndex;
BufPtr := Buffer;
CurLetter := Letter;
end;
end;
procedure THelpIndex.Track(Start, Target: Word);
begin
if (CurIndex > Target) or (CurIndex < Start) then
begin
BufPtr := Buffer;
CurIndex := Start
end;
while CurIndex < Target do
GetToken;
end;
procedure THelpIndex.PositionTo(Index: Word);
var
Letter: Integer;
begin
Letter := SearchIndex(Index);
ReadLetter(Letter);
with Master[Letter] do
Track(StartIndex, Index);
end;
procedure THelpIndex.Parse;
var
MaxLength, CurOffset, BufOfs: Word;
TokenLen, Letter, CurRow, TokenCount, Rest, OldOfs, NewOfs: Word;
begin
TokenCount := 0;
CurOffset := 2;
MaxLength := 0;
CurIndex := 1;
ReadIndex(Buffer, CurOffset, 4096);
NewOfs := CurOffset;
BufPtr := Buffer;
BufOfs := PtrRec(BufPtr).Ofs;
for Letter := 0 to 26 do
with Master[Letter] do
begin
Offset := CurOffset;
StartIndex := TokenCount;
OldOfs := BufOfs;
Dec(CurIndex);
PtrRec(BufPtr).Ofs := BufOfs;
Rest := 0;
TokenLen := GetToken;
while (TokenLen > 0) and (LetterNum(IndexToken[1]) = Letter) do
begin
if MaxLength < TokenLen then
MaxLength := TokenLen;
Inc(TokenCount);
BufOfs := PtrRec(BufPtr).Ofs;
if BufOfs - PtrRec(Buffer).Ofs > 4016 then
begin
Rest := BufOfs - PtrRec(Buffer).Ofs;
NewOfs := NewOfs + Rest;
ReadIndex(Buffer, NewOfs, 4096);
BufPtr := Buffer;
BufOfs := PtrRec(Buffer).Ofs;
end;
TokenLen := GetToken;
end;
Size := BufOfs + Rest - OldOfs;
CurOffset := Offset + Size;
end;
if MaxLength = 0 then
MaxLength := 38;
ColumnCount := 76 div MaxLength;
if ColumnCount = 0 then
ColumnCount := 1;
if ColumnCount > 4 then
ColumnCount := 4;
ColumnWidth := 76 div ColumnCount;
CurRow := 1;
for Letter := 0 to 25 do
with Master[Letter] do
begin
StartRow := CurRow;
CurRow := CurRow + 3 + (Master[Letter+1].StartIndex - StartIndex +
ColumnCount - 1) div ColumnCount;
end;
Master[26].StartRow := CurRow;
MaxRow := CurRow + 3 + (MaxIndex - Master[26].StartIndex +
ColumnCount - 1) div ColumnCount;
SaveMaxRow := MaxRow;
end;
function THelpIndex.Read(Index: Word): Boolean;
begin
Read := False;
if ReadIndex(Buffer, 0, 2) <> 0 then
begin
Read := True;
MaxIndex := PWordArray(Buffer)^[0];
HasExample := False;
if Master[0].Offset = 0 then
Parse
else
MaxRow := SaveMaxRow;
CurLetter := 255;
end;
end;
procedure THelpIndex.GetRow(Row: Word; var Text: PChar; var Index: Word;
var Example: Boolean);
procedure MakeBold(Dest, Src: string; Width: Word); assembler;
asm
PUSH DS
CLD
LES DI,Dest
LDS SI,Src
MOV AL,ES:[DI]
SUB AH,AH
ADD DI,AX
LODSB
XCHG AX,CX
MOV AX,Width
SUB AX,CX
XCHG AX,DX
MOV AL,2
STOSB
REP MOVSB
STOSB
MOV CX,DX
MOV AL,' '
REP STOSB
SUB AL,AL
STOSB
MOV AX,Dest.Word[0]
XCHG AX,DI
SUB AX,DI
DEC AX
MOV ES:[DI],AL
POP DS
end;
const
S: string[87] = '';
var
Letter, R: Integer;
I: Word;
begin
THelpScreen.GetRow(Row, Text, Index, Example);
if Row < MaxRow then
begin
Index := 0;
Example := False;
S := #0;
Text := @S[1];
Letter := SearchRow(Row);
if Letter < 0 then
S := 'Turbo Help Index'#0
else
with Master[Letter] do
begin
ReadLetter(Letter);
R := Row - StartRow - 3;
if R < 0 then
begin
Index := StartIndex;
if (R = -2) and (Letter > 0) then
S := Chr(Letter + Ord('A') - 1) + #0;
end else
begin
I := StartIndex + R * ColumnCount;
Index := I;
Track(StartIndex, I);
if Letter = 26 then
I := MaxIndex - I
else
I := Master[Letter+1].StartIndex - I;
if I > ColumnCount then
I := ColumnCount;
while I > 0 do
begin
GetToken;
MakeBold(S, IndexToken, ColumnWidth);
Dec(I);
end;
end;
end;
end;
end;
function THelpIndex.Format(Width: Word; var P; N: Word): Boolean;
begin
Format := True;
end;
procedure THelpIndex.GetPos(Index: Word; var Row, Col: Integer; var Len: Word);
var
Letter: Integer;
begin
Letter := SearchIndex(Index);
with Master[Letter] do
begin
Row := StartRow + 3 + (Index - StartIndex) div ColumnCount;
Col := (Index - StartIndex) mod ColumnCount * ColumnWidth + 1;
PositionTo(Index);
Len := TokenLength;
end;
end;
function THelpIndex.GetIndex(var S: string; var Len: Word): Word;
function StrCmp(S1, S2: string): Boolean; assembler;
asm
PUSH DS
CLD
LDS SI,S2
LES DI,S1
MOV CL,ES:[DI]
CMPSB
JB @@3
SUB CH,CH
@@1: LODSB
CMP AL,'a'
JB @@2
CMP AL,'z'
JA @@2
AND AL,0DFH
@@2: SCASB
LOOPZ @@1
JNZ @@3
MOV AX,1
JMP @@4
@@3: SUB AX,AX
@@4: POP DS
end;
var
Letter: Integer;
Max, Index: Word;
Found: Boolean;
begin
GetIndex := $FFFE;
Len := 0;
if Length(S) > 0 then
begin
Letter := LetterNum(S[1]);
with Master[Letter] do
begin
ReadLetter(Letter);
Track(StartIndex, StartIndex);
if Letter = 26 then
Max := MaxIndex
else
Max := Master[Letter+1].StartIndex;
Index := StartIndex;
Found := False;
while (Index < Max) and not Found do
begin
GetToken;
if StrCmp(S, IndexToken) then
Found := True
else
Inc(Index);
end;
if Found then
begin
Len := Length(S);
GetIndex := Index
end;
end;
end else
GetIndex := 0;
end;
function THelpIndex.GetContext(Index: Word): Integer;
begin
PositionTo(Index);
GetToken;
GetContext := ContextNumber;
end;
procedure THelpIndex.GetExample(var StartPos, EndPos: TPos);
begin
THelpScreen.GetExample(StartPos, EndPos);
end;
constructor THelpTopic.Init(ABuffer: PChar; ABufSize: Word);
begin
THelpScreen.Init(ABuffer, ABufSize);
TopicSize := 0;
end;
function THelpTopic.Read(Index: Word): Boolean;
begin
Read := ReadTopic(Index, Buffer, BufSize, TopicSize, MaxIndex);
Reset;
CountRows;
FindExample;
end;
procedure THelpTopic.CountRows; assembler;
asm
PUSH DS
LDS SI,Self
MOV CX,[SI].TopicSize
LES DI,[SI].Buffer
SUB AX,AX
SUB BX,BX
CLD
@@1: JCXZ @@2
REPNZ SCASB
INC BX
JMP @@1
@@2: MOV [SI].MaxRow,BX
POP DS
end;
procedure THelpTopic.FindExample; assembler;
asm
PUSH DS
LDS SI,Self
MOV CX,[SI].TopicSize
LES DI,[SI].Buffer
MOV AL,5
SUB BX,BX
CLD
JCXZ @@1
REPNE SCASB
JNE @@1
INC BX
@@1: MOV [SI].HasExample,bl
POP DS
end;
procedure THelpTopic.Reset;
begin
BufPtr := Buffer;
CurRow := 0;
CurIndex := 0;
InExample := False;
end;
procedure THelpTopic.GoBack(Amount: Word);
begin
if CurRow <= Amount then
Reset
else
asm
PUSH DS
LDS SI,Self
LES DI,[SI].BufPtr
SUB AH,AH
SUB DX,DX
MOV BX,Amount
STD
INC BX
DEC DI
DEC DI
JMP @@7
@@1: MOV CX,0FFFFH
SUB AL,AL
REPNZ SCASB
NOT CX
PUSH DI
ADD DI,CX
DEC CX
JCXZ @@6
MOV AL,2
PUSH CX
PUSH DI
JMP @@3
@@2: INC DX
@@3: REPNE SCASB
JE @@2
MOV AL,5
POP DI
POP CX
JMP @@5
@@4: INC AH
@@5: REPNE SCASB
JE @@4
@@6: POP DI
@@7: DEC BX
JNZ @@1
AND AH,1
XOR [SI].InExample,AH
SHR DX,1
SUB [SI].CurIndex,DX
INC DI
INC DI
MOV [SI].BufPtr.Word[0],DI
MOV AX,Amount
SUB [SI].CurRow,AX
POP DS
CLD
end;
end;
procedure THelpTopic.GoForward(Amount: Word);
begin
if CurRow + Amount >= MaxRow then
Amount := MaxRow - CurRow - 1;
asm
PUSH DS
LDS SI,Self
LES DI,[SI].BufPtr
SUB AH,AH
SUB DX,DX
MOV BX,Amount
CLD
INC BX
JMP @@7
@@1: MOV CX,0FFFFH
SUB AL,AL
REPNZ SCASB
NOT CX
PUSH DI
SUB DI,CX
DEC CX
JCXZ @@6
MOV AL,2
PUSH CX
PUSH DI
JMP @@3
@@2: INC DX
@@3: REPNE SCASB
JE @@2
MOV AL,5
POP DI
POP CX
JMP @@5
@@4: INC AH
@@5: REPNE SCASB
JE @@4
@@6: POP DI
@@7: DEC BX
JNZ @@1
AND AH,1
XOR [SI].InExample,AH
SHR DX,1
ADD [SI].CurIndex,DX
MOV [SI].BufPtr.Word[0],DI
MOV AX,Amount
ADD [SI].CurRow,AX
POP DS
end;
end;
procedure THelpTopic.GoRow(Row: Word);
begin
if Row < CurRow then
if Row < CurRow shr 1 then
begin
Reset;
GoForward(Row)
end else
GoBack(CurRow - Row)
else if Row > CurRow then
GoForward(Row - CurRow);
end;
procedure THelpTopic.GetRow(Row: Word; var Text: PChar;var Index: Word;
var Example: Boolean);
begin
THelpScreen.GetRow(Row, Text, Index, Example);
if Row < MaxRow then
begin
GoRow(Row);
Text := BufPtr;
Index := CurIndex;
Example := InExample;
end;
end;
function THelpTopic.Format(Width: Word; var P; N: Word): Boolean; assembler;
var
SaveSP, IndexStart, Row: Word;
RowLen: byte;
NewMaxRow: Word;
HasControlChars: Boolean;
WordBuf: string[79];
WordLen: byte;
RowEnd: Word;
CurPosPtr: PPosArray;
TargetRow: Word;
TargetCol: Byte;
InKeyword: byte;
asm
PUSH DS
MOV SaveSP,SP
PUSH P.Word[2]
PUSH P.Word[0]
PUSH N
CALL SortPos
SUB AX,AX
MOV Row,AX
MOV NewMaxRow,AX
MOV HasControlChars,AL
SUB Width,1
LES AX,P
MOV CurPosPtr.Word[2],ES
SUB AX,4
MOV CurPosPtr.Word[0],AX
LDS SI,Self
LES DI,[SI].Buffer
MOV AX,DI
MOV CX,[SI].TopicSize
ADD AX,CX
DEC AX
ADD DI,[SI].BufSize
SUB DI,[SI].MaxIndex
SUB DI,[SI].MaxIndex
MOV IndexStart,DI
DEC DI
XCHG AX,SI
PUSH ES
POP DS
STD
REP MOVSB
CLD
XCHG SI,DI
INC SI
INC DI
CALL @@19
@@1: CMP SI,IndexStart
JAE @@30
@@2: MOV AL,[SI]
AND AL,AL
JZ @@3
CMP AL,' '
JNE @@6
@@3: CMP HasControlChars,0
JE @@4
CALL @@18
@@4: MOV AX,Row
CMP AX,TargetRow
JNE @@5
PUSH DS
PUSH SI
LDS SI,CurPosPtr
LDS SI,[SI]
MOV AX,NewMaxRow
MOV [SI].TPos.Row,AX
POP SI
POP DS
CALL @@19
JMP @@4
@@5: XCHG SI,DI
SUB AX,AX
MOV CX,0FFFFh
REPNZ SCASB
NOT CX
SUB DI,CX
XCHG SI,DI
REP MOVSB
INC NewMaxRow
JMP @@16
@@6: MOV RowLen,1
@@7: MOV AX,Row
CMP AX,TargetRow
JNE @@13
@@8: CMP BYTE PTR [SI],0
JE @@11
MOV AL,RowLen
CMP AL,1
JE @@9
CMP AL,TargetCol
JA @@11
@@9: CALL @@21
MOV AL,HasControlChars
AND AL,AL
JZ @@10
ADD AL,WordLen
CBW
CMP AX,Width
JBE @@10
CALL @@18
@@10: CALL @@28
JMP @@8
@@11: PUSH DS
PUSH SI
LDS SI,CurPosPtr
LDS SI,[SI]
MOV AX,NewMaxRow
MOV [SI].TPos.Row,AX
MOV AL,TargetCol
CMP AL,RowLen
JBE @@12
MOV RowLen,AL
@@12: MOV AL,HasControlChars
ADD AL,1
SUB AL,RowLen
ADD AL,TargetCol
MOV [SI].TPos.Col,AL
POP SI
POP DS
CALL @@19
JMP @@7
@@13: CMP BYTE PTR [SI],0
JE @@15
CALL @@21
MOV AL,HasControlChars
AND AL,AL
JZ @@14
ADD AL,WordLen
CBW
CMP AX,Width
JBE @@14
CALL @@18
@@14: CALL @@28
JMP @@13
@@15: INC SI
@@16: INC Row
JMP @@1
@@17: MOV SP,SaveSP
SUB AX,AX
JMP @@32
@@18: SUB AX,AX
STOSB
CMP DI,SI
JAE @@17
MOV HasControlChars,AL
INC NewMaxRow
RETN
@@19: MOV AX,N
AND AX,AX
MOV AX,-1
JZ @@20
DEC N
ADD CurPosPtr.Word[0],4
PUSH DS
PUSH SI
LDS SI,CurPosPtr
LDS SI,[SI]
MOV AL,[SI].TPos.Col
MOV TargetCol,AL
MOV AX,[SI].TPos.Row
POP SI
POP DS
@@20: MOV TargetRow,AX
RETN
@@21: PUSH ES
PUSH DI
SUB AX,AX
MOV WordLen,AL
MOV InKeyword,AL
MOV AX,SS
MOV ES,AX
LEA DI,WordBuf
@@22: MOV AL,[SI]
AND AL,AL
JZ @@25
CMP AL,' '
JNE @@23
TEST InKeyword,1
JZ @@26
@@23: INC SI
STOSB
CMP AL,7
JB @@24
INC WordLen
INC RowLen
JMP @@22
@@24: CMP AL,2
JNE @@22
XOR InKeyword,1
JMP @@22
@@25: MOV AL,' '
STOSB
INC RowLen
JMP @@27
@@26: MOV AL,' '
STOSB
INC SI
INC RowLen
CMP [SI],AL
JE @@26
@@27: MOV RowEnd,DI
POP DI
POP ES
RETN
@@28: PUSH DS
PUSH SI
MOV AX,SS
MOV DS,AX
LEA SI,WordBuf
MOV CX,RowEnd
SUB CX,SI
@@29: LODSB
STOSB
CMP AL,7
SBB HasControlChars,-1
LOOP @@29
POP SI
POP DS
RETN
@@30: CMP HasControlChars,0
JE @@31
CALL @@18
@@31: LDS SI,Self
SUB DI,[SI].Buffer.Word[0]
MOV [SI].TopicSize,DI
MOV AX,NewMaxRow
MOV [SI].MaxRow,AX
POP AX
PUSH DS
PUSH SI
MOV DS,AX
CALL Reset
PUSH DS
MOV AX,1
@@32: POP DS
end;
procedure THelpTopic.GetPos(Index: Word; var Row, Col: Integer; var Len: Word);
begin
if Index >= MaxIndex then
Index := MaxIndex - 1;
while (CurIndex <= Index) and (CurRow < MaxRow - 1) do
GoForward(1);
while CurIndex > Index do
GoBack(1);
Row := CurRow;
asm
PUSH DS
LDS SI,Self
MOV CX,Index
SUB CX,[SI].CurIndex
SHL CX,1
INC CX
LDS SI,[SI].BufPtr
MOV DX,1
@@1: LODSB
INC DX
CMP AL,7
JAE @@1
DEC DX
CMP AL,2
JNE @@1
LOOP @@1
@@2: LODSB
INC CX
CMP AL,2
JNE @@2
DEC CX
LDS SI,Col
MOV [SI],DX
LDS SI,Len
MOV [SI],CX
POP DS
end;
end;
function THelpTopic.GetIndex(var S: string; var Len: Word): Word; assembler;
asm
PUSH DS
LDS SI,Self
LES DI,[SI].Buffer
MOV CX,0FFFFh
MOV DX,[SI].MaxIndex
MOV AL,2
MOV DS,S.Word[2]
INC DX
CLD
@@1: DEC DX
JZ @@7
REPNE SCASB
JNZ @@7
MOV SI,S.Word[0]
MOV BH,[SI]
INC SI
SUB BL,BL
@@2: MOV AH,ES:[DI]
INC DI
INC BX
CMP AH,' '
JE @@2
DEC BX
INC BH
JMP @@5
@@3: CMP AH,'a'
JB @@4
CMP AH,'z'
JA @@4
AND AH,0DFH
@@4: CMP AH,[SI]
JNE @@6
INC SI
MOV AH,ES:[DI]
INC DI
INC BX
@@5: DEC BH
JNZ @@3
LDS SI,Self
MOV AX,[SI].MaxIndex
SUB AX,DX
LDS SI,Len
SUB BH,BH
MOV [SI],BX
JMP @@8
@@6: CMP AH,AL
JE @@1
REPNE SCASB
JZ @@1
@@7: MOV AX,0FFFEH
@@8: POP DS
end;
function THelpTopic.GetContext(Index: Word): Integer; assembler;
asm
PUSH DS
LDS SI,Self
MOV AX,[SI].MaxIndex
MOV BX,Index
CMP BX,AX
JB @@1
SUB AX,AX
JMP @@2
@@1: LES DI,[SI].Buffer
ADD DI,[SI].BufSize
SHL AX,1
SUB DI,AX
SHL BX,1
MOV AX,ES:[BX+DI]
@@2: POP DS
end;
procedure THelpTopic.FindPos(Ofs: Word; var P: TPos);
begin
if Ofs = $FFFF then
with P do
begin
Row := 0;
Col := 0
end else
asm
PUSH DS
STD
LDS SI,Self
LES DI,[SI].Buffer
MOV AX,Ofs
XCHG AX,DI
SUB AX,DI
NEG AX
XCHG AX,CX
SUB BX,BX
MOV DL,1
JCXZ @@3
@@1: DEC DI
MOV AL,ES:[DI]
CMP AL,7
SBB DL,-1
AND AL,AL
LOOPNZ @@1
JNZ @@3
INC CX
SUB AL,AL
@@2: JCXZ @@3
REPNZ SCASB
JNZ @@3
INC BX
JMP @@2
@@3: LDS SI,P
MOV [SI].TPos.Col,DL
MOV [SI].TPos.Row,BX
CLD
POP DS
end;
end;
function THelpTopic.FindChar(Num: Integer; C: Char): Word; assembler;
asm
PUSH DS
CLD
LDS SI,Self
LES DI,[SI].Buffer
MOV CX,[SI].TopicSize
MOV AL,C
MOV DX,Num
AND DX,DX
JZ @@2
@@1: JCXZ @@2
REPNE SCASB
JZ @@3
@@2: MOV AX,0FFFFH
JMP @@4
@@3: DEC DX
JNZ @@1
XCHG AX,DI
DEC AX
@@4: POP DS
end;
procedure THelpTopic.GetExample(var StartPos, EndPos: TPos);
begin
FindPos(FindChar(1, #5), StartPos);
FindPos(FindChar(2, #5), EndPos);
end;
end.