unit GvHint;

{ Graphics Vision 2.10 Context-Sensitive Hints,
  Copr. 1996,1997 Matthias Koeppe
}

{$ifndef FPK}
{$A+,B-,F+,G+,I-,O+,P-,Q-,R-,S-,T-,V+,X+}
{$endif FPK}

interface

{$ifdef FPK}
uses Objects, Drivers, GvMenus, GvDialog, BGI, GvFPK, ExtGraph, GvTexts;
{$else}
uses Objects, Drivers, GvMenus, GvDialog;
{$endif}

const
  HelpCtxMinimum: Word = 900;

type
  PHintStatusLine = ^THintStatusLine;
  THintStatusLine = object(TStatusLine)
    function Hint(AHelpCtx: Word): string; virtual;
  end;

  PFlyingHint = ^TFlyingHint;
  TFlyingHint = object(TStaticText)
    constructor Init(var Bounds: TRect; AText: string);
    procedure Draw; virtual;
    function Execute: Word; virtual;
  end;

implementation

{$ifndef FPK}
{$ifdef Windows}
uses WinGr, ExtGraph, GvTexts;
{$else}
uses MyFonts, MetaGr, ExtGraph, GvTexts;
{$endif}
{$endif}

function THintStatusLine.Hint(AHelpCtx: Word): string;
begin
  If AHelpCtx >= HelpCtxMinimum
  then Hint := GetStr(AHelpCtx)
  else Hint := ''
end;

constructor TFlyingHint.Init(var Bounds: TRect; AText: string);
var
  i, j, H, W, maxW: Integer;
begin
  SetTextParams(ftSansSerif, 0, 0, false);
  j := 1;
  maxW := 0;
  H := 0;
  AText := AText + ^m;
  For i := 1 to Length(AText) do
    If AText[i] = ^m
    then begin
      W := TextWidth(Copy(AText, j, i - j));
      j := i + 1;
      If W > maxW then maxW := W;
      Inc(H)
    end;
  Dec(AText[0]);
  If H = 1 then AText := ^c + AText;
  If Bounds.A.X + maxW + 6 < Bounds.B.X
  then Bounds.B.X := Bounds.A.X + maxW + 6
  else begin
    Bounds.B.X := Bounds.A.X - 16;
    Bounds.A.X := Bounds.B.X - maxW - 6;
    If Bounds.A.X < 0
    then begin
      Dec(Bounds.B.X, Bounds.A.X);
      Bounds.A.X := 0;
    end
  end;
  Bounds.B.Y := Bounds.A.Y + (TextHeight('') + 2) * H + 2;
  inherited Init(Bounds, AText)
end;

procedure TFlyingHint.Draw;
var S, H: String;
    P, L, I, J: Integer;
    R: TRect;
    Center: Boolean;

Begin
  {SetFillStyle(SolidFill, 14);
  Bar(0, 0, Size.X - 1, Size.Y - 1);}
  ColorFill(0, 0, Size.X, Size.Y, 15, 14, @CloseDot);

  SetColor(0);
  Rectangle(0, 0, Size.X - 1, Size.Y - 1);

  SetTextParams (GetStandardFont, 0, GetColor(2), false);
  GetText (S);
  L:=Length (S);
  R.Assign (2, 3, Size.X - 4, 0);
  Center:=False;
  P:=1;
  While R.A.Y < Size.Y do Begin
    If P <= L then Begin
      H:='';
      If S[P] = #3 then Begin
	Center := True;
	Inc (P);
      End;
      I := P;
      Repeat
	J := P;
	While (P <= L) and (S[P] = ' ') do Inc (P);
	While (P <= L) and (S[P] <> ' ') and (S[P] <> #13) do Inc (P);
	H:=H+Copy (S, J, P-J);
      Until (P > L) or (TextWidth (H) >= Size.X) or (S[P] = #13);
      If TextWidth (H) >= Size.X then Begin
	If J > I then Begin
	  Delete (H, J-I+1, Length (H)-J+I);
	  P := J;
	End
	Else Begin
	  Repeat Dec (H[0]) Until TextWidth (H) < Size.X;
	  P := I + Length (H);
	End;
      End;

      If Center then Begin
	SetTextJustify(CenterText, TopText);
	OutTextXY((R.A.X + R.B.X) div 2, R.A.Y, H);
      End
      Else Begin
	SetTextJustify(LeftText, TopText);
	OutTextXY(R.A.X, R.A.Y, H);
      End;

      While (P <= L) and (S[P] = ' ') do Inc (P);
      If (P <= L) and (S[P] = #13) then Begin
	Center := False;
	Inc (P);
	If (P <= L) and (S[P] = #10) then Inc (P);
      End;
    End;
    Inc (R.A.Y, TextHeight (H)+2);

  End;
end;

function TFlyingHint.Execute: Word;
var
  Event: TEvent;
begin
  repeat
    GetEvent(Event)
  until Event.What and (evMouse + evKeyboard + evCommand) <> 0;
  PutEvent(Event);
  Execute := 0
end;

end.
