[Back to OOP SWAG index] [Back to Main SWAG index] [Original]
(*
Last week I found a bug in HELPFile.PAS and called Borland. After describing
the error, the Borland representative agreed that it was a bug and that
it hasn't been reported. ThereFore, I will describe the bug here and give
a fix to the problem.
Problem:
Recall, HELPFile.PAS is the Turbo Vision Unit that TVDEMO.PAS Uses to
provide on-line help to Turbo Vision Programs. The problem that occurred
was that if a help panel was brought up that did not contain a cross
reference entry (i.e. hyperText link), and the user pressed [Tab] or
Shift+[Tab] then a run-time error is generated. notE: the run-time
error is generated if the Program is Compiled With Range Checking on.
if Range checking is off, then unpredicatable results occur.
to see the bug in action, do the following:
Fire up Turbo Pascal 6 and load the TVDEMO.PAS Program (by default it exists
in the TVDEMOS subdirectory). Make sure Range checking is turned on.
The option is in Options|Compiler. You will also want to turn debugging
on in both the TVDEMO.PAS and HELPFile.PAS Files. to do this, you must
edit the source code of both Files and change the {$D-} option to {$D+}
at the beginning of both Files.
Once you have done the above, press Ctrl+F9 to run TVDEMO. When TVDEMO
comes up, press F1 to bring up the help Window. Now, press Shift+[Tab]
or [Tab] and a RunTime error 201 will occur.
This bug arises from the fact that the HELPFile.PAS Unit assumes that
there will always be at least one cross reference field on a help panel.
Obviously, this is an invalid assumption.
Luckily, there is an easy solution to the problem. The following shows
how to change the HELPFile.PAS Program so that this error doesn't occur.
The only Procedure that needs to be changed is THelpViewer.HandleEvent.
*)
Procedure THelpViewer.HandleEvent(Var Event: TEvent);
Var
KeyPoint, Mouse: TPoint;
KeyLength: Byte;
KeyRef: Integer;
KeyCount: Integer;
{ 1. Add the following Variable declaration }
n : Integer;
Procedure MakeSelectVisible;
Var
D: TPoint;
begin
topic^.GetCrossRef(Selected, KeyPoint, KeyLength, KeyRef);
D := Delta;
if KeyPoint.X < D.X then D.X := KeyPoint.X;
if KeyPoint.X > D.X + Size.X then D.X := KeyPoint.X - Size.X;
if KeyPoint.Y < D.Y then D.Y := KeyPoint.Y;
if KeyPoint.Y > D.Y + Size.Y then D.Y := KeyPoint.Y - Size.Y;
if (D.X <> Delta.X) or (D.Y <> Delta.Y) then Scrollto(D.X, D.Y);
end;
Procedure Switchtotopic(KeyRef: Integer);
begin
if topic <> nil then Dispose(topic, Done);
topic := HFile^.Gettopic(KeyRef);
topic^.SetWidth(Size.X);
Scrollto(0, 0);
SetLimit(Limit.X, topic^.NumLines);
Selected := 1;
DrawView;
end;
begin
TScroller.HandleEvent(Event);
Case Event.What of
evKeyDown:
begin
Case Event.KeyCode of
kbTab:
begin
{ 2. Change This...
Inc(Selected);
if Selected > topic^.GetNumCrossRefs then Selected := 1;
MakeSelectVisible;
to this... }
Inc(Selected);
n := topic^.GetNumCrossRefs;
if n > 0 then
begin
if Selected > n then
Selected := 1;
MakeSelectVisible;
end
else
selected := 0;
{ end of Change 2 }
end;
kbShiftTab:
begin
{ 3. Change this ...
Dec(Selected);
if Selected = 0 then Selected := topic^.GetNumCrossRefs;
MakeSelectVisible;
to this... }
Dec(Selected);
n := topic^.GetNumCrossRefs;
if n > 0 then
begin
if Selected = 0 then
Selected := n;
MakeSelectVisible;
end
else
Selected := 0;
{ end of Change 3 }
end;
kbEnter:
begin
{ 4. Change this...
if Selected <= topic^.GetNumCrossRefs then
begin
topic^.GetCrossRef(Selected, KeyPoint, KeyLength, KeyRef);
Swithtotopic(KeyRef);
end;
to this...}
n := topic^.GetNumCrossRefs;
if n > 0 then
begin
if Selected <= n then
begin
topic^.GetCrossRef(Selected, KeyPoint, KeyLength, KeyRef);
Switchtotopic(KeyRef);
end;
end;
{ end of Change 4 }
end;
kbEsc:
begin
Event.What := evCommand;
Event.Command := cmClose;
PutEvent(Event);
end;
else
Exit;
end;
DrawView;
ClearEvent(Event);
end;
evMouseDown:
begin
MakeLocal(Event.Where, Mouse);
Inc(Mouse.X, Delta.X); Inc(Mouse.Y, Delta.Y);
KeyCount := 0;
Repeat
Inc(KeyCount);
if KeyCount > topic^.GetNumCrossRefs then Exit;
topic^.GetCrossRef(KeyCount, KeyPoint, KeyLength, KeyRef);
Until (KeyPoint.Y = Mouse.Y+1) and (Mouse.X >= KeyPoint.X) and
(Mouse.X < KeyPoint.X + KeyLength);
Selected := KeyCount;
DrawView;
if Event.Double then Switchtotopic(KeyRef);
ClearEvent(Event);
end;
evCommand:
if (Event.Command = cmClose) and (Owner^.State and sfModal <> 0) then
begin
endModal(cmClose);
ClearEvent(Event);
end;
end;
end;
[Back to OOP SWAG index] [Back to Main SWAG index] [Original]