home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Pascal / BPASCAL.700 / D12 / TVDEBUG.ZIP / TVDEBUG.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1992-10-01  |  13.4 KB  |  508 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Debuging Unit                   }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. unit TVDebug;  
  9.  
  10. interface
  11.  
  12. uses Objects, Drivers, Views, App, TextView;
  13.  
  14. const
  15.   cmTextWinAppendLine = 30000;
  16.  
  17.   { Custom options flag so TextInterior will know whether to scroll
  18.     its text as new lines are added or not.  Uses an unused bit of the
  19.     TView options field.    Default is not to scroll on append. }
  20.  
  21.   ofScrollonAppend = $0400;
  22.  
  23. type
  24.  
  25.   { TApplication }
  26.   {  A debugging version of APP's TApplication that will create a
  27.      Event window and a Log window on the bottom of the desktop. }
  28.   TApplication = object(App.TApplication)
  29.     constructor Init;
  30.     procedure GetEvent(var E: TEvent);  virtual;
  31.   end;
  32.   PApplication = ^TApplication;
  33.  
  34.   { TTextCollection }
  35.   {  Used internally by TTextInterior to hold the text to display }
  36.   PTextCollection = ^TTextCollection;
  37.   TTextCollection = object(TCollection)
  38.     procedure FreeItem(Item: Pointer); virtual;
  39.   end;
  40.  
  41.   { TTextInterior }
  42.   {  A scrolling view of the text stored in Lines. If the view recieves
  43.      a cmTextWinAppendLine as an evBroadcast the InfoPtr field is assumed
  44.      to contain a PString containing a new line to add to Lines. }
  45.   PTextInterior = ^TTextInterior;
  46.   TTextInterior = object(TScroller)
  47.     Lines: TTextCollection;
  48.     constructor Init( R: TRect; MaxLines: Integer;
  49.       AHScrollbar, AVScrollbar: PScrollbar);
  50.     destructor Done; virtual;
  51.     procedure Draw; virtual;
  52.     procedure HandleEvent(var E: TEvent); virtual;
  53.   end;
  54.  
  55.   { TTextWindow }
  56.   {  A window designed to contain a TTextInterior }
  57.   PTextWindow = ^TTextWindow;
  58.   TTextWindow = object(TWindow)
  59.     constructor Init(R: TRect; NewTitle: String; Num, MaxLines: Integer);
  60.     procedure MakeInterior( MaxLines: integer);  virtual;
  61.   end;
  62.  
  63.   { TEventWindow }
  64.   {  A text window that will a list of the last MaxLines events
  65.      sent to it by DisplayEvent.  TApplication above calls this
  66.      method upon receiving an event in GetEvent.  If this unit
  67.      is included after Views in a unit, all Message calls in that
  68.      unit are also displayed. NOTE: only one of these windows is
  69.      allowed.  If more than one is created the second will return
  70.      False from Valid causing InsertWindow to refuse to insert the
  71.      window in the desktop. }
  72.   PEventWindow = ^TEventWindow;
  73.   TEventWindow = object(TTextWindow)
  74.     Filters: Word;
  75.     constructor Init(var R: TRect; ATitle: String; Num, MaxLines: Integer);
  76.     destructor Done; virtual;
  77.     procedure DisplayEvent(var E: TEvent); virtual;
  78.     procedure FiltersDialog;
  79.     function GetPalette: PPalette; virtual;
  80.     procedure HandleEvent(var Event: TEvent); virtual;
  81.     procedure MakeInterior(Maxlines: Integer); virtual;
  82.     function Valid(Command: Word): Boolean; virtual; 
  83.   end;
  84.  
  85.   { TLogWindow }
  86.   {  Creating a TLogWindow will redirect all Write and Writeln's to
  87.      the window.  Only one of these windows should be created, if more
  88.      than one is create Valid will return False and InsertWindow will
  89.      refuse to insert the window into the desktop. }
  90.   PLogWindow = ^TLogWindow;
  91.   TLogWindow = object(TWindow)
  92.     Interior: PTerminal;
  93.     constructor Init(var Bounds: TRect; BufSize: Word);
  94.     destructor Done; virtual;
  95.     function Valid(Command: Word): Boolean; virtual;
  96.   end;
  97.  
  98. { An alternate Message from View's that will log the message to the
  99.   event window before sending it. }
  100. function Message(Receiver: PView; What, Command: Word;
  101.   InfoPtr: Pointer): Pointer;
  102.  
  103. implementation
  104.  
  105. uses Dos, Menus, Dialogs, KeyNamer, CmdNamer;
  106.  
  107. var
  108.   EventWindow: PEventWindow;
  109.  
  110. { TApplication }
  111.  
  112. constructor TApplication.Init;
  113. var
  114.   R: TRect;
  115. begin
  116.   inherited Init;
  117.  
  118.   BuiltInCommandNames;
  119.  
  120.   Desktop^.GetExtent(R);
  121.   R.Assign(R.A.X, R.B.Y-10, R.B.X div 2, R.B.Y);
  122.   InsertWindow(New(PEventWindow, Init(R, 'Event Window', wnNoNumber, 100)));
  123.  
  124.   Desktop^.GetExtent(R);
  125.   R.Assign(R.B.X div 2, R.B.Y-10, R.B.X, R.B.Y);
  126.   InsertWindow(New(PLogWindow, Init(R, 1024)));
  127. end;
  128.  
  129. procedure TApplication.GetEvent(var E: TEvent);
  130. begin
  131.   inherited GetEvent(E); 
  132.   if EventWindow <> nil then
  133.     EventWindow^.DisplayEvent(E);
  134. end;
  135.  
  136. const
  137.   CEWMenu = #9#10#11#12#13#14;
  138.  
  139. { TEWMenubox }
  140.  
  141. type
  142.   PEWMenubox = ^TEWMenubox;
  143.   TEWMenubox = object(TMenubox)
  144.     function GetPalette: PPalette; virtual;
  145.   end;
  146.  
  147. function TEWMenubox.GetPalette: PPalette;
  148. const
  149.   P: String[length(CEWMenu)] = CEWMenu;
  150. begin
  151.   GetPalette:= @P;
  152. end;
  153.  
  154. { TEWMenubar }
  155.  
  156. type
  157.   PEWMenubar = ^TEWMenubar;
  158.   TEWMenubar = object(TMenubar)
  159.     function GetPalette: PPalette; virtual;
  160.     function NewSubView(var Bounds: TRect; AMenu: PMenu;
  161.        AParentMenu: PMenuView): PMenuView; virtual;
  162.   end;
  163.  
  164. function TEWMenubar.GetPalette: PPalette;
  165. const
  166.   P: string[length(CEWMenu)] = CEWMenu;
  167. begin
  168.   GetPalette:= @P;
  169. end;
  170.  
  171. function TEWMenubar.NewSubView(var Bounds: TRect; AMenu: PMenu;
  172.   AParentMenu: PMenuView): PMenuView;
  173. begin
  174.   NewSubView := New(PEWMenuBox, Init(Bounds, AMenu, AParentMenu));
  175. end;
  176.  
  177. { TTextCollection }
  178.  
  179. procedure TTextCollection.FreeItem(Item: Pointer);
  180. begin
  181.   DisposeStr(Item);
  182. end;
  183.  
  184. { TTextInterior }
  185.  
  186. constructor TTextInterior.Init( R: TRect; MaxLines: Integer;
  187.   AHScrollbar, AVScrollbar: PScrollbar);
  188. begin
  189.   inherited Init(R, AHScrollbar, AVScrollbar);
  190.   if MaxLines = 0 then
  191.     Lines.Init(Size.X, 1)     { let it grow unchecked:  16K items max}
  192.   else
  193.     Lines.Init(Maxlines, 0);  { fix size and rollover when full }
  194.   SetLimit(128,Size.X);
  195.   GrowMode:= gfGrowHiX + gfGrowHiY;
  196. end;
  197.  
  198. destructor TTextInterior.Done;
  199. begin
  200.   Lines.Done;
  201.   inherited Done;
  202. end;
  203.  
  204. procedure TTextInterior.Draw;
  205. var
  206.   color: byte;
  207.   Y, I: Integer;
  208.   B: TDrawBuffer;
  209. begin                            { draw only what's visible }
  210.   Color:= GetColor(1);
  211.   for y:= 0 to Size.Y-1 do
  212.   begin
  213.     MoveChar(B,' ',Color,Size.X);
  214.     I:= Delta.Y+Y;
  215.     if (I < Lines.Count) and (Lines.At(I) <> nil) then
  216.       MoveStr(B, Copy(PString(Lines.At(I))^,Delta.X+1, Size.X), Color);
  217.     WriteLine(0,Y,Size.X,1,B);
  218.   end;
  219. end;
  220.  
  221. procedure TTextInterior.HandleEvent(var E: TEvent);
  222. begin
  223.   inherited HandleEvent(E);
  224.   case E.What of
  225.     evBroadcast:
  226.       case E.Command of
  227.         cmTextWinAppendLine:
  228.           begin
  229.             if Lines.Count < Lines.Limit then    { let it grow }
  230.             begin
  231.               Lines.Insert(E.Infoptr);
  232.               if Lines.Count > Size.Y then
  233.               begin
  234.                 SetLimit(128,Lines.Count);
  235.                 if (Owner <> nil) and
  236.                     ((Owner^.Options and ofScrollonAppend) <> 0) then
  237.                   VScrollbar^.SetValue(Lines.Count);
  238.               end;
  239.             end
  240.             else
  241.             begin
  242.               Lines.AtFree(0);           { zap the first item }
  243.               Lines.Insert(E.InfoPtr);   { before adding new one }
  244.             end;
  245.             DrawView;
  246.             end                           { show the changes }
  247.           else
  248.             Exit;
  249.          end;
  250.     else
  251.       Exit;
  252.     end;
  253.   ClearEvent(E);
  254. end;
  255.  
  256. { TTextWindow }
  257.  
  258. constructor TTextWindow.Init( R: TRect; NewTitle: String;
  259.   Num, MaxLines: Integer);
  260. begin
  261.   inherited Init(R,NewTitle, Num);
  262.   MakeInterior(MaxLines);
  263. end;
  264.  
  265. procedure TTextWindow.MakeInterior( MaxLines: Integer);
  266. var
  267.   R: TRect;
  268. begin
  269.   GetExtent(R);
  270.   R.Grow(-1, -1);
  271.   Insert(New(PTextInterior, Init(R, MaxLines,
  272.     StandardScrollBar(sbHorizontal),
  273.     StandardScrollBar(sbVertical))));
  274. end;
  275.  
  276. { TEventWindow }
  277.  
  278. const
  279.   cmEventFilters = 503;
  280.  
  281. constructor TEventWindow.Init(var R: TRect; ATitle: String; Num,
  282.   Maxlines: Integer);
  283. begin
  284.   inherited Init(R, ATitle, Num, MaxLines);
  285.  
  286.   { custom option flag for TextWindow's interior}
  287.   Options:= Options or (ofScrollOnAppend + ofFirstClick);
  288.   Filters := evMouse or evKeyBoard or evMessage;
  289.  
  290.   EventWindow := @Self; 
  291. end;
  292.  
  293. destructor TEventWindow.Done;
  294. begin
  295.   inherited Done;
  296.   EventWindow := nil;
  297. end;
  298.  
  299. procedure TEventWindow.DisplayEvent(var E: TEvent);
  300. var
  301.   st,xs,ys: String;
  302.   Event: Word;
  303. begin
  304.   st:='';
  305.   if State and sfSelected = 0 then
  306.   begin
  307.     Event := E.What and Filters;
  308.     case Event of
  309.       evNothing: Exit;
  310.       evMouseDown,
  311.       evMouseUp,
  312.       evMouseMove,
  313.       evMouseAuto:
  314.         begin
  315.           st := 'Mouse ';
  316.           case E.What of
  317.             evMouseDown: st := st + 'Down, ';
  318.             evMouseUp:   st := st + 'Up, ';
  319.             evMouseMove: st := st + 'Move, ';
  320.             evMouseAuto: st := st + 'Auto, ';
  321.           end;
  322.           case E.Buttons of
  323.             mbLeftButton:  st := st + 'Left Button, ';
  324.             mbRightButton: st := st + 'Right Button, ';
  325.             $04:           st := st + 'Center Button, ';
  326.           end;
  327.           if (E.Buttons <> 0) and E.Double then
  328.             st := st +'Double Click ';
  329.           Str(E.Where.X:0, xs);
  330.           Str(E.Where.Y:0, ys);
  331.           st := st + 'X:' + xs + ' Y:' + ys;
  332.         end;
  333.       evKeyDown:
  334.         begin
  335.           st := KeyName(E.KeyCode);
  336.           if st = '' then
  337.             st := KeyName(Word(E.CharCode));
  338.           st := 'Keyboard ' + st;
  339.         end;
  340.       evCommand,
  341.       evBroadcast:
  342.         begin
  343.           if E.What = evCommand then
  344.             st := 'Command '
  345.           else
  346.             st := 'Broadcast ';
  347.           St := Concat(St, CommandName(E.Command));
  348.         end;
  349.       else
  350.         Str(E.What:0, xs);
  351.         st := 'Unknown Event.What: ' + xs;
  352.       end;  {case}
  353.  
  354.       Views.Message(@Self, evBroadcast, cmTextWinAppendLine, NewStr(st));
  355.   end;  { if }
  356. end;
  357.  
  358. procedure TEventWindow.FiltersDialog;
  359. var
  360.   D: PDialog;
  361.   R: TRect;
  362.   DataRec: Word;
  363. begin
  364.   R.Assign(10,6,40,20);
  365.   D := New(PDialog, Init(R, 'Message Filters'));
  366.  
  367.   with D^ do
  368.   begin
  369.     R.Assign(7,2,22,10);
  370.     Insert(New(PCheckBoxes, Init(R,
  371.       NewSItem('Mouse ~D~own',
  372.       NewSItem('Mouse ~U~p',
  373.       NewSItem('Mouse ~M~ove',
  374.       NewSItem('Mouse ~A~uto',
  375.       NewSItem('~K~eyboard',
  376.       NewSItem('~C~ommand',
  377.       NewSItem('~B~roadcast',
  378.       NewSItem('~O~ther', nil)))))))))));
  379.  
  380.     R.Assign(5,11,13,13);
  381.     Insert(New(PButton, Init(R, 'Ok', cmOk, bfDefault)));
  382.  
  383.     R.Assign(14,11,24,13);
  384.     Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  385.  
  386.     SelectNext(False);
  387.   end;
  388.  
  389.   { transfer data from filters to a more linear datarec }
  390.   DataRec := 0;
  391.   DataRec := Filters and (evMouse or evKeyDown);
  392.   DataRec := DataRec or ((Filters - DataRec) shr 3);
  393.  
  394.   if Application^.ExecuteDialog(D, @DataRec) <> cmCancel then
  395.   begin
  396.     Filters := 0;
  397.     Filters := DataRec and (evMouse or evKeyDown);
  398.     Filters := Filters or ((DataRec - Filters) shl 3);
  399.   end;
  400. end;
  401.  
  402. function TEventWindow.GetPalette: PPalette;
  403. const
  404.   P: String[length(CBlueWindow)+ length(CMenuView)] = CBlueWindow + CMenuView;
  405. begin
  406.   GetPalette := @P;
  407. end;
  408.  
  409. procedure TEventWindow.HandleEvent(var Event: TEvent);
  410. begin
  411.   inherited HandleEvent(Event);
  412.   if (Event.What = evCommand) and (Event.Command = cmEventFilters) then
  413.   begin
  414.     FiltersDialog;
  415.     ClearEvent(Event);
  416.   end;
  417. end;
  418.  
  419. procedure TEventWindow.MakeInterior(Maxlines: Integer);
  420. var
  421.   R: TRect;
  422.   M: PMenubar;
  423. begin
  424.   GetExtent(R);
  425.   R.Grow(-1,-1);
  426.   R.B.Y:= R.A.Y+1;
  427.   Insert(New(PEWMenubar, Init(R, NewMenu(
  428.     NewSubMenu('~O~ptions', hcNoContext, NewMenu(
  429.       NewItem('~F~ilters', '', 0, cmEventFilters, hcNoContext, nil)),
  430.     nil)))));
  431.  
  432.   GetExtent(R);
  433.   R.Grow(-1, -1);
  434.   Inc(R.A.Y);
  435.   Insert(New(PTextInterior, Init(R, MaxLines,
  436.     StandardScrollBar(sbHorizontal+sbHandleKeyboard),
  437.     StandardScrollBar(sbVertical+sbHandleKeyboard))));
  438. end;
  439.  
  440. function TEventWindow.Valid(Command: Word): Boolean;
  441. begin
  442.   if inherited Valid(Command) then
  443.     Valid := EventWindow = @Self
  444.   else
  445.     Valid := False;
  446. end;
  447.  
  448. { TLogWindow }
  449.  
  450. function AssignedTo(var T: Text; View: PTextDevice): Boolean;
  451. begin
  452.   AssignedTo :=  Pointer((@TextRec(T).UserData)^) = View;
  453. end;
  454.  
  455. constructor TLogWindow.Init(var Bounds: TRect; BufSize: Word);
  456. var
  457.   R: TRect;
  458.   vSB, hSB: PScrollBar;
  459. begin
  460.   inherited Init(Bounds, 'Messages Log', wnNoNumber);
  461.   vSB := StandardScrollBar(sbVertical + sbHandleKeyboard);
  462.   Insert(vSB);
  463.   hsb := StandardScrollBar(sbHorizontal + sbHandleKeyboard);
  464.   Insert(hSB);
  465.   GetExtent(R);
  466.   R.Grow(-1, -1);
  467.   Interior := New(PTerminal, Init(R, hSB, vSB, BufSize));
  468.   Insert(Interior);
  469.   AssignDevice(Output, Interior);
  470.   Rewrite(Output);
  471. end;
  472.  
  473. destructor TLogWindow.Done;
  474. begin
  475.   if AssignedTo(Output, Interior) then
  476.   begin
  477.     Assign(Output, '');
  478.     Rewrite(Output);
  479.   end;
  480.   inherited Done;
  481. end;
  482.  
  483. function TLogWindow.Valid(Command: Word): Boolean;
  484. begin
  485.   Valid := AssignedTo(Output, Interior);
  486. end;
  487.  
  488. { Message }
  489.  
  490. function Message(Receiver: PView; What, Command: Word;
  491.   InfoPtr: Pointer): Pointer;
  492. var
  493.   E: TEvent;
  494. begin
  495.   E.What := What;
  496.   E.Command := Command;
  497.   E.Infoptr := Infoptr;
  498.  
  499.   { no point in displaying our own message to display an event...}
  500.  
  501.   if (EventWindow <> nil) and (Command <> cmTextWinAppendLine) then
  502.     EventWindow^.DisplayEvent(E);
  503.  
  504.   { pass the intercepted data on to the Message function it was intended for }
  505.   Message:= Views.Message(Receiver, What, Command, InfoPtr);
  506. end;
  507.  
  508. end.