unit OutputWn;

{$O+,F+,S-}

interface

uses Objects, Drivers, Views;

type

  POutputViewer = ^TOutputViewer;
  TOutputViewer = object(TScroller)
    constructor Init(var Bounds: TRect; AVScrollBar, AHScrollBar: PScrollBar);
    procedure Draw; virtual;
    procedure HandleEvent(var Event: TEvent); virtual;
    procedure Update;
    function Valid(Command: Word): Boolean; virtual;
  end;

const

  ROutputViewer: TStreamRec = (
    ObjType: 7001;
    VmtLink: Ofs(TypeOf(TOutputViewer)^);
    Load:    @TOutputViewer.Load;
    Store:   @TOutputViewer.Store
  );

function OutputWindow: PWindow;

implementation

uses TVars, VSwap, TWindows, Context;

constructor TOutputViewer.Init(var Bounds: TRect;
  AVScrollBar, AHScrollBar: PScrollBar);
begin
  TScroller.Init(Bounds, AHScrollBar, AVScrollBar);
  GrowMode := gfGrowHiX + gfGrowHiY;
  ShowCursor;
  EventMask := EventMask or evDebugger;
end;

procedure TOutputViewer.Draw;
var
  B: TDrawBuffer;
  I: Integer;
begin
  for I := 0 to Size.Y - 1 do
  begin
    GetUserScreen(Delta.X, Delta.Y + I, B, Size.X);
    WriteLine(0, I, Size.X, 1, B);
  end;
end;

procedure TOutputViewer.HandleEvent(var Event: TEvent);
var
  P, Q: TPoint;
begin
  TScroller.HandleEvent(Event);
  if Event.What and evMessage <> 0 then
    case Event.Command of
      cmRefreshInfo:
        begin
          Update;
          DrawView
        end;
      cmFindOutputWindow:
        ClearEvent(Event);
  end else if Event.What = evMouseDown then
  begin
    MakeLocal(Event.Where, Q);
    Q.X := Delta.X + Q.X;
    Q.Y := Delta.Y + Q.Y;
    repeat
      MakeLocal(Event.Where, P);
      ScrollTo(Q.X - P.X, Q.Y - P.Y);
    until not MouseEvent(Event, evMouseMove);
    ClearEvent(Event);
  end;
end;

procedure TOutputViewer.Update;
var
  P, Q: TPoint;
begin
  SetLimit(WordRec(ScreenSize).Lo, WordRec(ScreenSize).Hi);
  P.X := WordRec(CursorPos).Lo;
  P.Y := WordRec(CursorPos).Hi;
  SetCursor(P.X - Delta.X, P.Y - Delta.Y);
  Q := Delta;
  if Q.X > P.X then
    Q.X := P.X;
  if Q.X < P.X - Size.X + 1 then
    Q.X := P.X - Size.X + 1;
  if Q.Y > P.Y then
    Q.Y := P.Y;
  if Q.Y < P.Y-Size.Y + 1 then
    Q.Y := P.Y - Size.Y + 1;
  ScrollTo(Q.X, Q.Y);
end;

function TOutputViewer.Valid(Command: Word): Boolean;
begin
  Update;
  Valid := True;
end;

function OutputWindow: PWindow;
var
  R: TRect;
  Window: PWindow;
begin
  R.Assign(0, 16, 80, 23);
  Window := New(PTurboWindow, Init(R, 'Output', wnNoNumber, wpOutputWindow));
  with Window^ do
  begin
    HelpCtx := hcOutputWindow;
    Flags := Flags or (wfPutOnBottom + wfSaveable);
    GetExtent(R);
    R.Grow(-1, -1);
    Insert(New(POutputViewer,Init(R,
      StandardScrollBar(sbVertical + sbHandleKeyboard),
      StandardScrollBar(sbHorizontal + sbHandleKeyboard))));
  end;
  OutputWindow := Window;
end;

end.
