home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / windows / windum / windump.pas < prev   
Pascal/Delphi Source File  |  1994-05-27  |  22KB  |  829 lines

  1. {
  2.   WinDump : visualizzazione messaggi di debug.
  3.  
  4.   Written by:       Michele Mottini
  5.                     TERA S.r.l.
  6.                     CIS 100040,615
  7. }
  8. unit WinDump;
  9.  
  10. {$S-}
  11.  
  12. interface
  13.  
  14. uses
  15.   WinTypes,
  16.   WinProcs,
  17.   WinDos;
  18.  
  19. const
  20.   ScreenWidth = 80;
  21.  
  22.   WindowOrg: TPoint =                       { CRT window origin }
  23.     (X: cw_UseDefault; Y: cw_UseDefault);
  24.   WindowSize: TPoint =                      { CRT window size }
  25.     (X: cw_UseDefault; Y: cw_UseDefault);
  26.   ScreenSize: TPoint = (X: ScreenWidth; Y: 32000);   { Virtual screen dimensions }
  27.   Cursor: TPoint = (X: 0; Y: 0);            { Cursor location }
  28.   Origin: TPoint = (X: 0; Y: 0);            { Client area origin }
  29.   InactiveTitle: PChar = '(Inactive %s)';   { Inactive window title }
  30.   AutoTracking: Boolean = True;             { Track cursor on Write? }
  31.   CheckEOF: Boolean = False;                { Allow Ctrl-Z for EOF? }
  32.   CheckBreak: Boolean = True;               { Allow Ctrl-C for break? }
  33.  
  34. var
  35.   WindowTitle: array[0..79] of Char;        { CRT window title }
  36.  
  37. procedure InitWinCrt;
  38. procedure DoneWinCrt;
  39.  
  40. procedure WriteBuf(Buffer: PChar; Count: Word);
  41. procedure WriteChar(Ch: Char);
  42.  
  43. function KeyPressed: Boolean;
  44. function ReadKey: Char;
  45. function ReadBuf(Buffer: PChar; Count: Word): Word;
  46.  
  47. procedure GotoXY(X, Y: Integer);
  48. function WhereX: Integer;
  49. function WhereY: Integer;
  50. procedure ClrScr;
  51. procedure ClrEol;
  52.  
  53. procedure CursorTo(X, Y: Integer);
  54. procedure ScrollTo(X, Y: Integer);
  55. procedure TrackCursor;
  56.  
  57. procedure AssignCrt(var F: Text);
  58.  
  59. implementation {==============================================================}
  60.  
  61. uses
  62.   Arit,
  63.   Strings,
  64.   Strings2,
  65.   Streams;
  66.  
  67. type
  68.  
  69.    { Double word record }
  70.  
  71.   LongRec = record
  72.     Lo, Hi: Integer;
  73.   end;
  74.  
  75.     { MinMaxInfo array }
  76.  
  77.   PMinMaxInfo = ^TMinMaxInfo;
  78.   TMinMaxInfo = array[0..4] of TPoint;
  79.  
  80. { CRT window procedure }
  81.  
  82. function CrtWinProc(Window: HWnd;
  83.                     Message, WParam: Word;
  84.                     LParam: Longint): Longint; export; forward;
  85.  
  86. { CRT window class }
  87.  
  88. const
  89.   CrtClass: TWndClass = (
  90.     style: cs_HRedraw + cs_VRedraw;
  91.     lpfnWndProc: @CrtWinProc;
  92.     cbClsExtra: 0;
  93.     cbWndExtra: 0;
  94.     hInstance: 0;
  95.     hIcon: 0;
  96.     hCursor: 0;
  97.     hbrBackground: 0;
  98.     lpszMenuName: nil;
  99.     lpszClassName: 'TPWinDump');
  100.  
  101. const
  102.   CrtWindow: HWnd = 0;                  { CRT window handle }
  103.   FirstLine: Integer = 0;               { First line in circular buffer }
  104.   KeyCount: Integer = 0;                { Count of keys in KeyBuffer }
  105.   Created: Boolean = False;           { CRT window created? }
  106.   Focused: Boolean = False;             { CRT window focused? }
  107.   Reading: Boolean = False;             { Reading from CRT window? }
  108.   Painting: Boolean = False;            { Handling wm_Paint? }
  109.  
  110. var
  111.   SaveExit: Pointer;                    { Saved exit procedure pointer }
  112.   ScreenBuffer: TSCollection;           { Screen buffer }
  113.   ClientSize: TPoint;                   { Client area dimensions }
  114.   Range: TPoint;                        { Scroll bar ranges }
  115.   CharSize: TPoint;                     { Character cell size }
  116.   CharAscent: Integer;                  { Character ascent }
  117.   DC: HDC;                              { Global device context }
  118.   PS: TPaintStruct;                     { Global paint structure }
  119.   SaveFont: HFont;                      { Saved device context font }
  120.   KeyBuffer: array[0..63] of Char;      { Keyboard type-ahead buffer }
  121.  
  122. {---------------------------------------------------------- Scroll keys table }
  123.  
  124. type
  125.   TScrollKey = record
  126.     Key: Byte;
  127.     Ctrl: Boolean;
  128.     SBar: Byte;
  129.     Action: Byte;
  130.   end;
  131.  
  132. const
  133.   ScrollKeyCount = 12;
  134.   ScrollKeys: array[1..ScrollKeyCount] of TScrollKey = (
  135.     (Key: vk_Left;  Ctrl: False; SBar: sb_Horz; Action: sb_LineUp),
  136.     (Key: vk_Right; Ctrl: False; SBar: sb_Horz; Action: sb_LineDown),
  137.     (Key: vk_Left;  Ctrl: True;  SBar: sb_Horz; Action: sb_PageUp),
  138.     (Key: vk_Right; Ctrl: True;  SBar: sb_Horz; Action: sb_PageDown),
  139.     (Key: vk_Home;  Ctrl: False; SBar: sb_Horz; Action: sb_Top),
  140.     (Key: vk_End;   Ctrl: False; SBar: sb_Horz; Action: sb_Bottom),
  141.     (Key: vk_Up;    Ctrl: False; SBar: sb_Vert; Action: sb_LineUp),
  142.     (Key: vk_Down;  Ctrl: False; SBar: sb_Vert; Action: sb_LineDown),
  143.     (Key: vk_Prior; Ctrl: False; SBar: sb_Vert; Action: sb_PageUp),
  144.     (Key: vk_Next;  Ctrl: False; SBar: sb_Vert; Action: sb_PageDown),
  145.     (Key: vk_Home;  Ctrl: True;  SBar: sb_Vert; Action: sb_Top),
  146.     (Key: vk_End;   Ctrl: True;  SBar: sb_Vert; Action: sb_Bottom));
  147.  
  148. {------------------------------------------------------------- Configurazione }
  149.  
  150. const
  151.   SecName = 'WinDump';
  152.   WindowKey = 'Window';
  153.  
  154. procedure LoadConfig;
  155. var
  156.   Buffer : array[0..80] of char;
  157.   P : PChar;
  158. begin
  159.   GetProfileString(SecName,WindowKey,'',Buffer,SizeOf(Buffer));
  160.   P := Buffer;
  161.   if P^ <> #0 then begin
  162.     WindowOrg.X := StrToIntDef(StrToken(P,','),cw_UseDefault);
  163.     if P^ <> #0 then begin
  164.       WindowOrg.Y := StrToIntDef(StrToken(P,','),cw_UseDefault);
  165.       if P^ <> #0 then begin
  166.         WindowSize.X := StrToIntDef(StrToken(P,','),cw_UseDefault);
  167.         if P^ <> #0 then begin
  168.           WindowSize.Y := StrToIntDef(P,cw_UseDefault);
  169.         end;
  170.       end;
  171.     end;
  172.   end;
  173. end; { LoadConfig }
  174.  
  175. procedure SaveConfig;
  176. var
  177.   Buffer : array[0..80] of char;
  178. begin
  179.   IntToStr(WindowOrg.X,Buffer);
  180.   StrCat(Buffer,',');
  181.   IntToStr(WindowOrg.Y,Buffer+StrLen(Buffer));
  182.   StrCat(Buffer,',');
  183.   IntToStr(WindowSize.X,Buffer+StrLen(Buffer));
  184.   StrCat(Buffer,',');
  185.   IntToStr(WindowSize.Y,Buffer+StrLen(Buffer));
  186.   WriteProfileString(SecName,WindowKey,Buffer);
  187. end; { SaveConfig }
  188.  
  189. {--------------------------------------------- Accesso al buffer dello schermo }
  190.  
  191. var
  192.   LineBuffer : array[0..ScreenWidth] of char;
  193.  
  194. function ScreenPtr(X,Y : integer): PChar;
  195.   {- Return pointer to location in screen buffer.}
  196. var
  197.   L : integer;
  198. begin
  199.   inc(Y, FirstLine);
  200.   if Y >= ScreenSize.Y then dec(Y,ScreenSize.Y);
  201.   if Y >= ScreenBuffer.Count then LineBuffer[0] := #0
  202.   else StrCopy(LineBuffer,PChar(ScreenBuffer.At(Y)));
  203.   L := StrLen(LineBuffer);
  204.   FillChar(PChar(LineBuffer+L)^,ScreenWidth-L,' ');
  205.   ScreenPtr := PChar(LineBuffer+X);
  206. end; { ScreenPtr }
  207.  
  208. procedure ClearLine(Y : integer);
  209. var
  210.   LinePtr : PChar;
  211. begin
  212.   inc(Y, FirstLine);
  213.   if Y >= ScreenSize.Y then dec(Y,ScreenSize.Y);
  214.   if Y < ScreenBuffer.Count then begin
  215.     LinePtr := PChar(ScreenBuffer.At(Y));
  216.     FillChar(LinePtr^,StrLen(LinePtr),' ');
  217.   end;
  218. end; { ClearLine }
  219.  
  220. procedure ClearToEol(X,Y : integer);
  221. var
  222.   LinePtr : PChar;
  223.   L : integer;
  224. begin
  225.   inc(Y, FirstLine);
  226.   if Y >= ScreenSize.Y then dec(Y,ScreenSize.Y);
  227.   if Y < ScreenBuffer.Count then begin
  228.     LinePtr := PChar(ScreenBuffer.At(Y));
  229.     L := StrLen(LinePtr);
  230.     while X < L do begin
  231.       LinePtr[X] := ' ';
  232.       inc(X);
  233.     end;
  234.   end;
  235. end; { ClearToEol }
  236.  
  237. procedure PutChar(X,Y : integer; C : char);
  238. var
  239.   LinePtr,NewLinePtr : PChar;
  240.   L : integer;
  241. begin
  242.   inc(Y, FirstLine);
  243.   if Y >= ScreenSize.Y then dec(Y,ScreenSize.Y);
  244.   if Y >= ScreenBuffer.Count then begin
  245.     FillChar(LineBuffer,succ(X),' ');
  246.     LineBuffer[succ(X)] := #0;
  247.     while Y >= ScreenBuffer.Count do ScreenBuffer.Insert(StrNew(LineBuffer));
  248.   end;
  249.   LinePtr := PChar(ScreenBuffer.At(Y));
  250.   if X >= StrLen(LinePtr) then begin
  251.     GetMem(NewLinePtr,X+2);
  252.     StrCopy(NewLinePtr,LinePtr);
  253.     L := StrLen(NewLinePtr);
  254.     while L < X do begin
  255.       NewLinePtr[L] := ' ';
  256.       inc(L);
  257.     end;
  258.     NewLinePtr[X+1] := #0;
  259.     StrDispose(LinePtr);
  260.     LinePtr := NewLinePtr;
  261.     ScreenBuffer.AtPut(Y,LinePtr);
  262.   end;
  263.   LinePtr[X] := C;
  264. end; { PutChar }
  265.  
  266. {------------------------------------------------------------ Display context }
  267.  
  268. procedure InitDeviceContext;
  269.   {- Allocate device context }
  270. begin
  271.   if Painting then
  272.     DC := BeginPaint(CrtWindow, PS)
  273.   else
  274.     DC := GetDC(CrtWindow);
  275.   SaveFont := SelectObject(DC, GetStockObject(System_Fixed_Font));
  276.   SetTextColor(DC, GetSysColor(color_WindowText));
  277.   SetBkColor(DC, GetSysColor(color_Window));
  278. end; { InitDeviceContext }
  279.  
  280. procedure DoneDeviceContext;
  281.   {- Release device context }
  282. begin
  283.   SelectObject(DC, SaveFont);
  284.   if Painting then
  285.     EndPaint(CrtWindow, PS) else
  286.     ReleaseDC(CrtWindow, DC);
  287. end; { DoneDeviceContext }
  288.  
  289. procedure ShowCursor;
  290.   {- Show caret }
  291. begin
  292.   CreateCaret(CrtWindow, 0, CharSize.X, 2);
  293.   SetCaretPos((Cursor.X - Origin.X) * CharSize.X,
  294.     (Cursor.Y - Origin.Y) * CharSize.Y + CharAscent);
  295.   ShowCaret(CrtWindow);
  296. end; { ShowCursor }
  297.  
  298. procedure HideCursor;
  299.   {- Hide caret }
  300. begin
  301.   DestroyCaret;
  302. end; { HideCursor }
  303.  
  304. procedure SetScrollBars;
  305.   {- Update scroll bars }
  306. begin
  307.   SetScrollRange(CrtWindow, sb_Horz, 0, Max(1, Range.X), False);
  308.   SetScrollPos(CrtWindow, sb_Horz, Origin.X, True);
  309.   SetScrollRange(CrtWindow, sb_Vert, 0, Max(1, Range.Y), False);
  310.   SetScrollPos(CrtWindow, sb_Vert, Origin.Y, True);
  311. end; {SetScrollBars }
  312.  
  313. procedure Terminate;
  314.   {- Terminate CRT window.}
  315. begin
  316.   if Focused and Reading then HideCursor;
  317.   Halt(255);
  318. end;  { Terminate }
  319.  
  320. procedure CursorTo(X, Y: Integer);
  321.   {- Set cursor position }
  322. begin
  323.   Cursor.X := Max(0, Min(X, ScreenSize.X - 1));
  324.   Cursor.Y := Max(0, Min(Y, ScreenSize.Y - 1));
  325. end; { CursorTo }
  326.  
  327. procedure ScrollTo(X,Y : Integer);
  328.   {- Scroll window to given origin.}
  329. begin
  330.   if Created then begin
  331.     X := Max(0, Min(X, Range.X));
  332.     Y := Max(0, Min(Y, Range.Y));
  333.     if (X <> Origin.X) or (Y <> Origin.Y) then
  334.     begin
  335.       if X <> Origin.X then SetScrollPos(CrtWindow, sb_Horz, X, True);
  336.       if Y <> Origin.Y then SetScrollPos(CrtWindow, sb_Vert, Y, True);
  337.       ScrollWindow(CrtWindow,
  338.     (Origin.X - X) * CharSize.X,
  339.     (Origin.Y - Y) * CharSize.Y, nil, nil);
  340.       Origin.X := X;
  341.       Origin.Y := Y;
  342.       UpdateWindow(CrtWindow);
  343.     end;
  344.   end;
  345. end; { ScrollTo }
  346.  
  347. procedure TrackCursor;
  348.   {- Scroll to make cursor visible.}
  349. begin
  350.   ScrollTo(Max(Cursor.X - ClientSize.X + 1, Min(Origin.X, Cursor.X)),
  351.     Max(Cursor.Y - ClientSize.Y + 1, Min(Origin.Y, Cursor.Y)));
  352. end; { TrackCursor }
  353.  
  354. procedure ShowText(L, R : Integer);
  355.   {- Update text on cursor line.}
  356. begin
  357.   if L < R then begin
  358.     InitDeviceContext;
  359.     TextOut(DC, (L - Origin.X) * CharSize.X,
  360.       (Cursor.Y - Origin.Y) * CharSize.Y,
  361.       ScreenPtr(L, Cursor.Y), R - L);
  362.     DoneDeviceContext;
  363.   end;
  364. end; { ShowText }
  365.  
  366. procedure WriteBuf(Buffer: PChar; Count: Word);
  367.   {- Write text buffer to CRT window.}
  368. var
  369.   L, R: Integer;
  370.  
  371.   procedure NewLine;
  372.   begin
  373.     ShowText(L, R);
  374.     L := 0;
  375.     R := 0;
  376.     Cursor.X := 0;
  377.     Inc(Cursor.Y);
  378.     if Cursor.Y = ScreenSize.Y then begin
  379.       Dec(Cursor.Y);
  380.       Inc(FirstLine);
  381.       if FirstLine = ScreenSize.Y then FirstLine := 0;
  382.       ClearLine(Cursor.Y);
  383.       ScrollWindow(CrtWindow, 0, -CharSize.Y, nil, nil);
  384.       UpdateWindow(CrtWindow);
  385.     end;
  386.   end; { NewLine }
  387.  
  388. begin { WriteBuf }
  389.   InitWinCrt;
  390.   L := Cursor.X;
  391.   R := Cursor.X;
  392.   while Count > 0 do begin
  393.     case Buffer^ of
  394.       #32..#255:
  395.     begin
  396.       PutChar(Cursor.X, Cursor.Y,Buffer^);
  397.       Inc(Cursor.X);
  398.       if Cursor.X > R then R := Cursor.X;
  399.       if Cursor.X = ScreenSize.X then NewLine;
  400.     end;
  401.       #13:
  402.     NewLine;
  403.       #8:
  404.     if Cursor.X > 0 then begin
  405.       Dec(Cursor.X);
  406.       PutChar(Cursor.X, Cursor.Y,' ');
  407.       if Cursor.X < L then L := Cursor.X;
  408.     end;
  409.       #7:
  410.         MessageBeep(0);
  411.     end;
  412.     Inc(Buffer);
  413.     Dec(Count);
  414.   end;
  415.   ShowText(L, R);
  416.   if AutoTracking then TrackCursor;
  417. end; { WriteBuf }
  418.  
  419. procedure WriteChar(Ch: Char);
  420.   {- Write character to CRT window }
  421. begin
  422.   WriteBuf(@Ch,1);
  423. end; { WriteChar }
  424.  
  425. function KeyPressed: Boolean;
  426.   {- Return keyboard status }
  427. var
  428.   M: TMsg;
  429. begin
  430.   InitWinCrt;
  431.   while PeekMessage(M, 0, 0, 0, pm_Remove) do
  432.   begin
  433.     if M.Message = wm_Quit then Terminate;
  434.     TranslateMessage(M);
  435.     DispatchMessage(M);
  436.   end;
  437.   KeyPressed := KeyCount > 0;
  438. end; { KeyPressed }
  439.  
  440. function ReadKey: Char;
  441.   {- Read key from CRT window.}
  442. begin
  443.   TrackCursor;
  444.   if not KeyPressed then
  445.   begin
  446.     Reading := True;
  447.     if Focused then ShowCursor;
  448.     repeat WaitMessage until KeyPressed;
  449.     if Focused then HideCursor;
  450.     Reading := False;
  451.   end;
  452.   ReadKey := KeyBuffer[0];
  453.   Dec(KeyCount);
  454.   Move(KeyBuffer[1], KeyBuffer[0], KeyCount);
  455. end; { ReadKey }
  456.  
  457. function ReadBuf(Buffer: PChar; Count: Word): Word;
  458.   {- Read text buffer from CRT window.}
  459. var
  460.   Ch: Char;
  461.   I: Word;
  462. begin
  463.   I := 0;
  464.   repeat
  465.     Ch := ReadKey;
  466.     case Ch of
  467.       #8:
  468.     if I > 0 then begin
  469.       Dec(I);
  470.       WriteChar(#8);
  471.     end;
  472.       #32..#255:
  473.     if I < Count - 2 then
  474.     begin
  475.       Buffer[I] := Ch;
  476.       Inc(I);
  477.       WriteChar(Ch);
  478.     end;
  479.     end;
  480.   until (Ch = #13) or (CheckEOF and (Ch = #26));
  481.   Buffer[I] := Ch;
  482.   Inc(I);
  483.   if Ch = #13 then
  484.   begin
  485.     Buffer[I] := #10;
  486.     Inc(I);
  487.     WriteChar(#13);
  488.   end;
  489.   TrackCursor;
  490.   ReadBuf := I;
  491. end; { ReadBuf }
  492.  
  493. procedure GotoXY(X, Y: Integer);
  494.   {- Set cursor position.}
  495. begin
  496.   CursorTo(X - 1, Y - 1);
  497. end; { GotoXY }
  498.  
  499. function WhereX: Integer;
  500.   {- Return cursor X position.}
  501. begin
  502.   WhereX := Cursor.X + 1;
  503. end; { WhereX }
  504.  
  505. function WhereY: Integer;
  506.   {- Return cursor Y position.}
  507. begin
  508.   WhereY := Cursor.Y + 1;
  509. end; { WhereY }
  510.  
  511. procedure ClrScr;
  512.   {- Clear screen.}
  513. begin
  514.   InitWinCrt;
  515.   ScreenBuffer.FreeAll;
  516.   Longint(Cursor) := 0;
  517.   Longint(Origin) := 0;
  518.   SetScrollBars;
  519.   InvalidateRect(CrtWindow, nil, True);
  520.   UpdateWindow(CrtWindow);
  521. end; { ClrScr }
  522.  
  523. procedure ClrEol;
  524.   {- Clear to end of line.}
  525. begin
  526.   InitWinCrt;
  527.   ClearToEol(Cursor.X, Cursor.Y);
  528.   ShowText(Cursor.X, ScreenSize.X);
  529. end; { ClrEol }
  530.  
  531. {-------------------------------------------------- Gestione messaggi Windows }
  532.  
  533. procedure WindowCreate;
  534.   {- wm_Create message handler.}
  535. begin
  536.   Created := True;
  537.   ScreenBuffer.Init(25,25);
  538.   if not CheckBreak then
  539.     EnableMenuItem(GetSystemMenu(CrtWindow, False), sc_Close,
  540.       mf_Disabled + mf_Grayed);
  541. end; { WindowCreate }
  542.  
  543. procedure WindowPaint;
  544.   {- wm_Paint message handler.}
  545. var
  546.   X1, X2, Y1, Y2: Integer;
  547. begin
  548.   Painting := True;
  549.   InitDeviceContext;
  550.   X1 := Max(0, PS.rcPaint.left div CharSize.X + Origin.X);
  551.   X2 := Min(ScreenSize.X,
  552.     (PS.rcPaint.right + CharSize.X - 1) div CharSize.X + Origin.X);
  553.   Y1 := Max(0, PS.rcPaint.top div CharSize.Y + Origin.Y);
  554.   Y2 := Min(ScreenSize.Y,
  555.     (PS.rcPaint.bottom + CharSize.Y - 1) div CharSize.Y + Origin.Y);
  556.   while Y1 < Y2 do begin
  557.     TextOut(DC, (X1 - Origin.X) * CharSize.X, (Y1 - Origin.Y) * CharSize.Y,
  558.       ScreenPtr(X1, Y1), X2 - X1);
  559.     Inc(Y1);
  560.   end;
  561.   DoneDeviceContext;
  562.   Painting := False;
  563. end; { WindowPaint }
  564.  
  565. procedure WindowScroll(Which, Action, Thumb: Integer);
  566.   {- wm_VScroll and wm_HScroll message handler.}
  567. var
  568.   X,Y : integer;
  569.  
  570.   function GetNewPos(Pos, Page, Range: Integer): Integer;
  571.   begin
  572.     case Action of
  573.       sb_LineUp        : GetNewPos := Pos - 1;
  574.       sb_LineDown      : GetNewPos := Pos + 1;
  575.       sb_PageUp        : GetNewPos := Pos - Page;
  576.       sb_PageDown      : GetNewPos := Pos + Page;
  577.       sb_Top           : GetNewPos := 0;
  578.       sb_Bottom        : GetNewPos := Range;
  579.       sb_ThumbPosition : GetNewPos := Thumb;
  580.     else
  581.       GetNewPos := Pos;
  582.     end;
  583.   end; { GetNewPos }
  584.  
  585. begin { WindowScroll }
  586.   X := Origin.X;
  587.   Y := Origin.Y;
  588.   case Which of
  589.     sb_Horz: X := GetNewPos(X, ClientSize.X div 2, Range.X);
  590.     sb_Vert: Y := GetNewPos(Y, ClientSize.Y, Range.Y);
  591.   end;
  592.   ScrollTo(X, Y);
  593. end; { WindowScroll }
  594.  
  595. procedure WindowResize(X, Y: Integer);
  596.   {- wm_Size message handler.}
  597. begin
  598.   if Focused and Reading then HideCursor;
  599.   ClientSize.X := X div CharSize.X;
  600.   ClientSize.Y := Y div CharSize.Y;
  601.   Range.X := Max(0, ScreenSize.X - ClientSize.X);
  602.   Range.Y := Max(0, ScreenSize.Y - ClientSize.Y);
  603.   Origin.X := Min(Origin.X, Range.X);
  604.   Origin.Y := Min(Origin.Y, Range.Y);
  605.   SetScrollBars;
  606.   if Focused and Reading then ShowCursor;
  607. end; { WindowResize }
  608.  
  609. procedure WindowMinMaxInfo(MinMaxInfo: PMinMaxInfo);
  610.   {- wm_GetMinMaxInfo message handler.}
  611. var
  612.   X, Y: Integer;
  613.   Metrics: TTextMetric;
  614. begin
  615.   InitDeviceContext;
  616.   GetTextMetrics(DC, Metrics);
  617.   CharSize.X := Metrics.tmMaxCharWidth;
  618.   CharSize.Y := Metrics.tmHeight + Metrics.tmExternalLeading;
  619.   CharAscent := Metrics.tmAscent;
  620.   X := Min(ScreenSize.X * CharSize.X + GetSystemMetrics(sm_CXVScroll),
  621.     GetSystemMetrics(sm_CXScreen)) + GetSystemMetrics(sm_CXFrame) * 2;
  622.   Y := GetSystemMetrics(sm_CYScreen) + GetSystemMetrics(sm_CYFrame) * 2;
  623.   MinMaxInfo^[1].x := X;
  624.   MinMaxInfo^[1].y := Y;
  625.   MinMaxInfo^[3].x := CharSize.X * 16 + GetSystemMetrics(sm_CXVScroll) +
  626.     GetSystemMetrics(sm_CXFrame) * 2;
  627.   MinMaxInfo^[3].y := CharSize.Y * 4 + GetSystemMetrics(sm_CYHScroll) +
  628.     GetSystemMetrics(sm_CYFrame) * 2 + GetSystemMetrics(sm_CYCaption);
  629.   MinMaxInfo^[4].x := X;
  630.   MinMaxInfo^[4].y := Y;
  631.   DoneDeviceContext;
  632. end; { WindowMinMaxInfo }
  633.  
  634. procedure WindowChar(Ch: Char);
  635.   {- wm_Char message handler.}
  636. begin
  637.   if CheckBreak and (Ch = #3) then Terminate;
  638.   if KeyCount < SizeOf(KeyBuffer) then begin
  639.     KeyBuffer[KeyCount] := Ch;
  640.     Inc(KeyCount);
  641.   end;
  642. end; { WindowChar }
  643.  
  644. procedure WindowKeyDown(KeyDown: Byte);
  645.   {- wm_KeyDown message handler.}
  646. var
  647.   CtrlDown: Boolean;
  648.   I: Integer;
  649. begin
  650.   if CheckBreak and (KeyDown = vk_Cancel) then Terminate;
  651.   CtrlDown := GetKeyState(vk_Control) < 0;
  652.   for I := 1 to ScrollKeyCount do
  653.     with ScrollKeys[I] do
  654.       if (Key = KeyDown) and (Ctrl = CtrlDown) then begin
  655.     WindowScroll(SBar, Action, 0);
  656.     Exit;
  657.       end;
  658. end; { WindowKeyDown }
  659.  
  660. procedure WindowSetFocus;
  661.   {- wm_SetFocus message handler }
  662. begin
  663.   Focused := True;
  664.   if Reading then ShowCursor;
  665. end; { WindowSetFocus }
  666.  
  667. procedure WindowKillFocus;
  668.   {- wm_KillFocus message handler }
  669. begin
  670.   if Reading then HideCursor;
  671.   Focused := False;
  672. end; { WindowKillFocus }
  673.  
  674. procedure WindowDestroy;
  675.   {- wm_Destroy message handler.}
  676. var
  677.   Rect : TRect;
  678. begin
  679.   GetWindowRect(CrtWindow,Rect);
  680.   with Rect do begin
  681.     WindowOrg.X  := Left;
  682.     WindowOrg.Y  := Top;
  683.     WindowSize.X := Right-Left;
  684.     WindowSize.Y  := Bottom-Top;
  685.   end;
  686.   ScreenBuffer.Done;
  687.   Longint(Cursor) := 0;
  688.   Longint(Origin) := 0;
  689.   Created := False;
  690. end; { WindowDestroy }
  691.  
  692. function CrtWinProc(Window: HWnd;
  693.                     Message, WParam: Word;
  694.                     LParam: Longint): Longint;
  695.   {- CRT window procedure }
  696. begin
  697.   CrtWinProc := 0;
  698.   CrtWindow := Window;
  699.   case Message of
  700.     wm_Create        : WindowCreate;
  701.     wm_Paint         : WindowPaint;
  702.     wm_VScroll       : WindowScroll(sb_Vert, WParam, LongRec(LParam).Lo);
  703.     wm_HScroll       : WindowScroll(sb_Horz, WParam, LongRec(LParam).Lo);
  704.     wm_Size          : WindowResize(LongRec(LParam).Lo, LongRec(LParam).Hi);
  705.     wm_GetMinMaxInfo : WindowMinMaxInfo(PMinMaxInfo(LParam));
  706.     wm_Char          : WindowChar(Char(WParam));
  707.     wm_KeyDown       : WindowKeyDown(Byte(WParam));
  708.     wm_SetFocus      : WindowSetFocus;
  709.     wm_KillFocus     : WindowKillFocus;
  710.     wm_Destroy       : WindowDestroy;
  711.   else
  712.     CrtWinProc := DefWindowProc(Window, Message, WParam, LParam);
  713.   end;
  714. end; { CrtWinProc }
  715.  
  716. {---------------------------------------------------- Text file device driver }
  717.  
  718. function CrtOutput(var F: TTextRec): Integer; far;
  719.   {- Text file device driver output function }
  720. begin
  721.   if F.BufPos <> 0 then
  722.   begin
  723.     WriteBuf(PChar(F.BufPtr), F.BufPos);
  724.     F.BufPos := 0;
  725.     KeyPressed;
  726.   end;
  727.   CrtOutput := 0;
  728. end; { CrtOutput }
  729.  
  730. function CrtInput(var F: TTextRec): Integer; far;
  731.   {- Text file device driver input function }
  732. begin
  733.   F.BufEnd := ReadBuf(PChar(F.BufPtr), F.BufSize);
  734.   F.BufPos := 0;
  735.   CrtInput := 0;
  736. end; { CrtInput }
  737.  
  738. function CrtClose(var F: TTextRec): Integer; far;
  739.   {- Text file device driver close function }
  740. begin
  741.   CrtClose := 0;
  742. end; { CrtClose }
  743.  
  744. function CrtOpen(var F: TTextRec): Integer; far;
  745.   {- Text file device driver open function }
  746. begin
  747.   if F.Mode = fmInput then
  748.   begin
  749.     F.InOutFunc := @CrtInput;
  750.     F.FlushFunc := nil;
  751.   end else
  752.   begin
  753.     F.Mode := fmOutput;
  754.     F.InOutFunc := @CrtOutput;
  755.     F.FlushFunc := @CrtOutput;
  756.   end;
  757.   F.CloseFunc := @CrtClose;
  758.   CrtOpen := 0;
  759. end; { CrtOpen }
  760.  
  761. procedure AssignCrt(var F: Text);
  762.   {- Assign text file to CRT device }
  763. begin
  764.   with TTextRec(F) do begin
  765.     Handle := $FFFF;
  766.     Mode := fmClosed;
  767.     BufSize := SizeOf(Buffer);
  768.     BufPtr := @Buffer;
  769.     OpenFunc := @CrtOpen;
  770.     Name[0] := #0;
  771.   end;
  772. end; { AssignCrt }
  773.  
  774. {----------------------------------------------- Apertura e chiusura finestra }
  775.  
  776. procedure InitWinCrt;
  777.   {- Create CRT window if required.}
  778. begin
  779.   if not Created then begin
  780.     CrtWindow := CreateWindow(
  781.       CrtClass.lpszClassName,
  782.       WindowTitle,
  783.       ws_OverlappedWindow + ws_HScroll + ws_VScroll,
  784.       WindowOrg.X, WindowOrg.Y,
  785.       WindowSize.X, WindowSize.Y,
  786.       0,
  787.       0,
  788.       HInstance,
  789.       nil);
  790.     ShowWindow(CrtWindow, CmdShow);
  791.     UpdateWindow(CrtWindow);
  792.   end;
  793. end; { InitWinCrt }
  794.  
  795. procedure DoneWinCrt;
  796.   {- Destroy CRT window if required }
  797. begin
  798.   if Created then DestroyWindow(CrtWindow);
  799. end; { DoneWinCrt }
  800.  
  801. procedure ExitWinCrt; far;
  802.   {- WinCrt unit exit procedure.}
  803. begin
  804.   ExitProc := SaveExit;
  805.   SaveConfig;
  806.   DoneWinCrt;
  807. end; { ExitWinCrt }
  808.  
  809. {---------------------------------------------------------------------- Main }
  810.  
  811. begin
  812.   if HPrevInst = 0 then begin
  813.     CrtClass.hInstance := HInstance;
  814.     CrtClass.hIcon := LoadIcon(0, idi_Application);
  815.     CrtClass.hCursor := LoadCursor(0, idc_Arrow);
  816.     CrtClass.hbrBackground := color_Window + 1;
  817.     RegisterClass(CrtClass);
  818.   end;
  819.   AssignCrt(Input);
  820.   Reset(Input);
  821.   AssignCrt(Output);
  822.   Rewrite(Output);
  823.   GetModuleFileName(HInstance, WindowTitle, SizeOf(WindowTitle));
  824.   OemToAnsi(WindowTitle, WindowTitle);
  825.   LoadConfig;
  826.   SaveExit := ExitProc;
  827.   ExitProc := @ExitWinCrt;
  828. end. { unit WinDump }
  829.