home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / BININT.ZIP / BININT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-10-23  |  7.9 KB  |  303 lines

  1. {
  2.  BININT offers a way to access normally hidden information while within a
  3.  BINED event handler. See BININT.DOC for details.
  4.  
  5.  Written by Kim Kokkonen, TurboPower Software.
  6.  Released to the public domain.
  7.  Compuserve [72457,2131]
  8.  
  9.  Version 1.0, 10/22/88
  10.    first release
  11. }
  12.  
  13. {$R-,S-,I-,B-,F-}
  14.  
  15. unit BinInt;
  16.   {-Make BINED internals available to event handlers}
  17.  
  18. interface
  19.  
  20. uses
  21.   BinEd;
  22.  
  23. type
  24.   EdIntRec =
  25.     record
  26.       EditSeg : Word;             {Segment where editor control block is located}
  27.       BuffOfs : Word;             {Offset in EditSeg where text buffer starts}
  28.       LineOfs : Word;             {Offset in EditSeg where offset of current line is stored}
  29.       StrtOfs : Word;             {Offset in EditSeg where line buffer is stored}
  30.       CurrOfs : Word;             {Offset in EditSeg where offset of position in line buffer is stored}
  31.       CharOfs : Word;             {Offset in EditSeg of character buffer}
  32.       OptnOfs : Word;             {Offset in EditSeg of editor options}
  33.     end;
  34.  
  35. procedure FindInternals(EdData : EdCB; var E : EdIntRec);
  36.   {-Initialize an internal data record}
  37.  
  38. function CurrLineOfs(var E : EdIntRec) : Word;
  39.   {-Return text buffer offset at start of current line}
  40.  
  41. function CurrChar(var E : EdIntRec) : Char;
  42.   {-Return character at cursor position}
  43.  
  44. function LinePos(var E : EdIntRec) : Byte;
  45.   {-Return cursor position within current line, 1..247}
  46.  
  47. function LineLen(var E : EdIntRec) : Byte;
  48.   {-Return length of current line}
  49.  
  50. function CurrLine(var E : EdIntRec) : string;
  51.   {-Return the current line as a string}
  52.  
  53. function EditOptions(var E : EdIntRec) : Byte;
  54.   {-Return the current editor options}
  55.  
  56. procedure ClearKbd(var E : EdIntRec);
  57.   {-Clears both the BIOS and internal BINED keyboard buffers}
  58.  
  59. procedure StuffKey(W : Word);
  60.   {-Stuffs a keystroke into the keyboard buffer}
  61.  
  62.   {======================================================================}
  63.  
  64. implementation
  65.  
  66. const
  67.   KbdStart = $1E;
  68.   KbdEnd = $3C;
  69. type
  70.   Barray = array[0..30000] of Byte;
  71.   BarrayPtr = ^Barray;
  72.   SO =
  73.     record
  74.       O : Word;
  75.       S : Word;
  76.     end;
  77. var
  78.   KbdHead : Word absolute $40 : $1A;
  79.   KbdTail : Word absolute $40 : $1C;
  80.  
  81.   function Search(var Buffer; BuffLen : Word;
  82.                   var Match; MatchLen : Word) : Pointer;
  83.     {-Return pointer to start of match, nil if none}
  84.   var
  85.     B : BarrayPtr;
  86.     M : BarrayPtr;
  87.     I : Word;
  88.     J : Word;
  89.     Matched : Boolean;
  90.   begin
  91.     B := @Buffer;
  92.     M := @Match;
  93.     for I := 1 to BuffLen do begin
  94.       if B^[0] = M^[0] then begin
  95.         {Start of a match, try the rest}
  96.         if MatchLen = 1 then
  97.           Matched := True
  98.         else begin
  99.           J := 1;
  100.           repeat
  101.             Matched := (B^[J] = M^[J]);
  102.             Inc(J);
  103.           until not Matched or (J = MatchLen);
  104.         end;
  105.         if Matched then begin
  106.           {Complete match}
  107.           Search := B;
  108.           Exit;
  109.         end;
  110.       end;
  111.       {Move to next byte}
  112.       Inc(SO(B).O);
  113.     end;
  114.     {No match}
  115.     Search := nil;
  116.   end;
  117.  
  118.   function CodeMatch(B, M : BarrayPtr; Len : Word) : Boolean;
  119.     {-Return true if B^ matches M^ after discounting addresses}
  120.   var
  121.     MB : Byte;
  122.     I : Word;
  123.   begin
  124.     for I := 0 to Len-1 do begin
  125.       MB := M^[I];
  126.       if MB <> 0 then
  127.         if MB <> B^[I] then begin
  128.           CodeMatch := False;
  129.           Exit;
  130.         end;
  131.     end;
  132.     CodeMatch := True;
  133.   end;
  134.  
  135.   procedure FindInternals(EdData : EdCB; var E : EdIntRec);
  136.     {-Initialize an internal data record}
  137.   type
  138.     WordPtr = ^Word;
  139.   const
  140.     {Code we must find to determine data offsets}
  141.     Match0 : array[0..7] of Byte =
  142.     ($C3,                         {RET}
  143.      $C3,                         {RET}
  144.      $F6, $06, $00, $00, $01,     {TEST [Options],01}
  145.      $C3);                        {RET}
  146.     Match1 : array[0..18] of Byte =
  147.     ($C6, $07, $1A,               {MOV BYTE PTR [BX],1Ah}
  148.      $8B, $16, $00, $00,          {MOV DX,[LineOfs]}
  149.      $2B, $16, $00, $00,          {SUB DX,[BuffOfs]}
  150.      $BE, $00, $00,               {MOV SI,StrtOfs}
  151.      $FC,                         {CLD}
  152.      $3B, $36, $00, $00);         {CMP SI,[CurrOfs]}
  153.     Match2 : array[0..7] of Byte =
  154.     ($5B,                         {POP BX}
  155.      $80, $3E, $00, $00, $FF,     {CMP [BufChar],$FF}
  156.      $B0, $FF);                   {MOV AL,$FF}
  157.   var
  158.     B0 : BarrayPtr;
  159.     B1 : BarrayPtr;
  160.     B2 : BarrayPtr;
  161.   begin
  162.     {All zeros will indicate error}
  163.     FillChar(E, SizeOf(EdIntRec), 0);
  164.  
  165.     {B0 is base of the binary editor code segment}
  166.     B0 := Ptr(Seg(InitBinaryEditor), 0);
  167.  
  168.     {Find code for editor options}
  169.     B0 := Search(B0^, 10000, Match0, 4);
  170.     if B0 = nil then
  171.       {Not found}
  172.       Exit;
  173.     if not CodeMatch(B0, @Match0, SizeOf(Match0)) then
  174.       {Not a complete match}
  175.       Exit;
  176.  
  177.     {Find code for various buffer offsets}
  178.     B1 := Search(B0^, 10000, Match1, 5);
  179.     if B1 = nil then
  180.       Exit;
  181.     if not CodeMatch(B1, @Match1, SizeOf(Match1)) then
  182.       Exit;
  183.  
  184.     {Find code for character buffer}
  185.     B2 := Search(B1^, 10000, Match2, 3);
  186.     if B2 = nil then
  187.       Exit;
  188.     if not CodeMatch(B2, @Match2, SizeOf(Match2)) then
  189.       Exit;
  190.  
  191.     {Initialize the internals record}
  192.     with E do begin
  193.       EditSeg := EdData.DataSeg;
  194.       BuffOfs := SO(EdData.Buffer).O;
  195.       OptnOfs := WordPtr(@B0^[4])^;
  196.       LineOfs := WordPtr(@B1^[5])^;
  197.       StrtOfs := WordPtr(@B1^[12])^;
  198.       CurrOfs := WordPtr(@B1^[17])^;
  199.       CharOfs := WordPtr(@B2^[3])^;
  200.     end;
  201.   end;
  202.  
  203.   function CurrLineOfs(var E : EdIntRec) : Word;
  204.     {-Return text buffer offset of start of current line}
  205.   begin
  206.     with E do
  207.       if EditSeg = 0 then
  208.         CurrLineOfs := $FFFF
  209.       else
  210.         CurrLineOfs := MemW[EditSeg:LineOfs]-BuffOfs;
  211.   end;
  212.  
  213.   function CurrChar(var E : EdIntRec) : Char;
  214.     {-Return character at cursor position}
  215.   begin
  216.     with E do
  217.       if EditSeg = 0 then
  218.         CurrChar := #$FF
  219.       else
  220.         CurrChar := Char(Mem[EditSeg:MemW[EditSeg:CurrOfs]]);
  221.   end;
  222.  
  223.   function LinePos(var E : EdIntRec) : Byte;
  224.     {-Return cursor position within current line}
  225.   begin
  226.     with E do
  227.       if EditSeg = 0 then
  228.         LinePos := $FF
  229.       else
  230.         LinePos := MemW[EditSeg:CurrOfs]-StrtOfs+1;
  231.   end;
  232.  
  233.   function LineLen(var E : EdIntRec) : Byte;
  234.     {-Return length of current line}
  235.   var
  236.     O : Word;
  237.   begin
  238.     with E do
  239.       if EditSeg = 0 then
  240.         LineLen := $FF
  241.       else begin
  242.         O := StrtOfs+247;
  243.         while (O >= StrtOfs) and (Mem[EditSeg:O] = $20) do
  244.           Dec(O);
  245.         LineLen := O+1-StrtOfs;
  246.       end;
  247.   end;
  248.  
  249.   function CurrLine(var E : EdIntRec) : string;
  250.     {-Return the current line as a string}
  251.   var
  252.     L : string;
  253.     LL : Byte absolute L;
  254.   begin
  255.     LL := LineLen(E);
  256.     if LL = $FF then
  257.       LL := 0
  258.     else with E do
  259.       Move(Mem[EditSeg:StrtOfs], L[1], LL);
  260.     CurrLine := L;
  261.   end;
  262.  
  263.   function EditOptions(var E : EdIntRec) : Byte;
  264.     {-Return the current editor options}
  265.   begin
  266.     with E do
  267.       if EditSeg = 0 then
  268.         EditOptions := $FF
  269.       else
  270.         EditOptions := Mem[EditSeg:OptnOfs];
  271.   end;
  272.  
  273.   procedure ClearKbd(var E : EdIntRec);
  274.     {-Clears both the BIOS and internal BINED keyboard buffers}
  275.   begin
  276.     with E do
  277.       if EditSeg <> 0 then begin
  278.         {Clear BIOS keyboard buffer}
  279.         KbdHead := KbdTail;
  280.         {Clear BINED character buffer}
  281.         Mem[EditSeg:CharOfs] := $FF;
  282.       end;
  283.   end;
  284.  
  285.   procedure StuffKey(W : Word);
  286.     {-Stuffs a keystroke into the keyboard buffer}
  287.   var
  288.     SaveKbdTail : Word;
  289.   begin
  290.     SaveKbdTail := KbdTail;
  291.     if KbdTail = KbdEnd then
  292.       KbdTail := KbdStart
  293.     else
  294.       Inc(KbdTail, 2);
  295.     if KbdTail = KbdHead then
  296.       {Buffer full, ignore request}
  297.       KbdTail := SaveKbdTail
  298.     else
  299.       MemW[$40:SaveKbdTail] := W;
  300.   end;
  301.  
  302. end.
  303.