home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / turbopas / toadln5.arc / TOADLN5.INC < prev    next >
Text File  |  1988-08-24  |  23KB  |  454 lines

  1.  
  2. PROCEDURE ToadLn(VAR S : Str255);
  3.   BEGIN
  4.     Inline(
  5. {;v1.5}
  6. {; - fixed BS error}
  7. {; - handling/addressing local variables with conventional}
  8. {;   .ASM format.}
  9. {;   [bp+4] = VAR S doubleword vector}
  10. {;   [bp-4] = string starting xy coordinates}
  11. {;   [bp-6] = screen width}
  12. {;   [bp-7] = insert flag}
  13. {; - adding insert key toggle (default insert On)}
  14. {;Codes returned in AX from a svc 0, Int 16H call:}
  15. {;CTRLU  EQU 1615H  ;^U}
  16. {;CTRLZ  EQU 2C1AH  ;^Z}
  17. {;DNARR  EQU 5000H  ;Cursor down}
  18. {;UPARR  EQU 4800H  ;Cursor up}
  19. {;HOMKEY EQU 4700H  ;Home key}
  20. {;ENDKEY EQU 4F00H  ;End key}
  21. {;LFTARR EQU 4B00H  ;Cursor left}
  22. {;RTARR  EQU 4D00H  ;Cursor right}
  23. {;INSKEY EQU 5200H  ;Insert key}
  24. {;DELKEY EQU 5300H  ;Delete key}
  25. {;BSKEY  EQU 0E08H  ;Backspace/Rubout key}
  26. {;CRKEY  EQU 1C0DH  ;Return key}
  27.  
  28.   $81/$EC/$05/$00 {  sub  sp,5           ;space for 2 integers, 1 boolean}
  29.   /$1E            {  push DS             ;save DS}
  30.   /$E8/$BA/$01    {  call InitScr        ;init screen vars}
  31.                   
  32.   /$C5/$76/$04    {  lds  si,[bp+4]      ;DS:SI = string vector (>S[bp])}
  33.   /$8C/$D8        {  mov  ax,DS}
  34.   /$8E/$C0        {  mov  ES,ax          ;ES:DI also string vector}
  35.   /$C6/$46/$F9/$FF{  mov  byte [bp-7],$FF  ;assume insert mode}
  36.   /$E8/$08/$01    {  call PadStr         ;pad, display, home cursor}
  37.                   
  38.                   {;Clear keyboard buffer}
  39.                   {ClrKbd:}
  40.   /$B4/$01        {  mov  ah,1           ;report if char is ready}
  41.   /$CD/$16        {  int  $16            ;BIOS}
  42.   /$74/$06        {  jz   KeyIn          ;kbd buff is empty}
  43.   /$30/$E4        {   xor ah,ah          ; Svc 0, read next kbd char}
  44.   /$CD/$16        {   int $16            ; BIOS}
  45.   /$EB/$F4        {   jmp short ClrKbd   ; Until kbd buff is empty}
  46.                   
  47.                   {;Kbd buffer is now empty}
  48.                   {;Now get/process the user's keyboard input.}
  49.                   {KeyIn:}
  50.   /$E8/$23/$00    {  call GetKey         ;Read, process kbd char}
  51.   /$09/$C0        {  or   ax,ax          ;no cursor moving?}
  52.   /$74/$F9        {  je   KeyIn          ;right, next key}
  53.   /$3D/$0D/$1C    {   cmp  ax,$1C0D      ; Was it a CR or ^Z?}
  54.   /$74/$05        {   je   ReturnStr     ; yep, done}
  55.                   {;insure cursor is updated}
  56.   /$E8/$37/$01    {    call AbsCur       ;  repsn cursor, update len}
  57.   /$EB/$EF        {    jmp  short Keyin  ;  next key, please}
  58.                   
  59.                   {ReturnStr:}
  60.   /$BF/$FF/$FF    {  mov di,$FFFF        ;force char ptr to end}
  61.   /$E8/$2F/$01    {  call AbsCur         ;cursor to screen end}
  62.   /$E8/$F9/$00    {  call ShowStr        ;update length, display}
  63.   /$B8/$0D/$0E    {  mov  ax,$0E0D       ;CR}
  64.   /$CD/$10        {  int  $10}
  65.   /$B0/$0A        {  mov  al,$0A         ;LF}
  66.   /$CD/$10        {  int  $10}
  67.   /$E9/$BF/$01    {  jmp  Done           ;finished}
  68.  
  69.                   {GetKey:}
  70.                   {;Processes the keyboard char, acts as required.}
  71.   /$30/$E4        {  xor  ah,ah          ;svc 0, read next kbd char}
  72.   /$CD/$16        {  int  $16            ;BIOS}
  73.                   {;^U clears the string and screen line.}
  74.   /$3D/$15/$16    {  cmp  ax,$1615       ;Is it a ^U?}
  75.   /$75/$07        {  jne  LftArrTst      ;nope}
  76.   /$C6/$04/$00    {   mov byte [si],0    ; clear str length}
  77.   /$E8/$C7/$00    {   call PadStr        ; clear screen/string}
  78.   /$C3            {   ret}
  79.                   
  80.                   {LftArrTst:}
  81.                   {;Left Arrow key moves left 1 char, stops at 1st char.}
  82.   /$3D/$00/$4B    {  cmp  ax,$4B00       ;how about cursor left?}
  83.   /$75/$02        {  jne  RtArrTst       ;nope}
  84.   /$4F            {   dec  di            ; back up ptr}
  85.   /$C3            {   ret}
  86.                   
  87.                   {RtArrTst:}
  88.                   {;Right Arrow key moves right 1 char,}
  89.                   {;stops at last char (+1 if not 255th char)}
  90.   /$3D/$00/$4D    {  cmp  ax,$4D00       ;right cursor?}
  91.   /$75/$02        {  jne  DelTst         ;nope}
  92.   /$47            {   inc  di            ; bump 1 to right}
  93.   /$C3            {   ret}
  94.                   
  95.                   {DelTst:}
  96.                   {;Delete key rubs out the cursor char,}
  97.                   {; does NOT move cursor, moves rest of string left.}
  98.   /$3D/$00/$53    {  cmp  ax,$5300       ;Delete key?}
  99.   /$74/$0A        {  je   DoBS           ;yep, skip to common code}
  100.                   
  101.                   {BSTst:}
  102.                   {;BS moves left 1 char and deletes THAT char.}
  103.                   {;No action if we're at first char}
  104.   /$3D/$08/$0E    {  cmp  ax,$0E08       ;Is it a BS? (Rubout)}
  105.   /$75/$2A        {  jne  DnArrTst       ;nope}
  106.                   
  107.   /$4F            {  dec  di             ;back up next char ptr}
  108.   /$39/$F7        {  cmp  di,si          ;did we back up to length byte}
  109.   /$76/$21        {  jbe  NoBS           ;yep, no action}
  110.                   
  111.                   {DoBS:}
  112.   /$C6/$05/$B0    {  mov  byte [di],$B0  ;"delete" char right here}
  113.   /$E8/$ED/$00    {  call AbsCur         ;fix cursor psn,current str psn}
  114.   /$89/$F8        {  mov  ax,di          ;new current psn}
  115.   /$29/$F0        {  sub  ax,si          ;- start = next char ofs}
  116.   /$39/$C8        {  cmp  ax,cx          ;is cursor within string? (not at end)}
  117.   /$73/$0F        {  jae  BSShow         ;nope, at end or beyond}
  118.                   
  119.   /$29/$C1        {  sub  cx,ax          ;len - cur psn = bytes to move}
  120.   /$56            {  push si             ;save str start}
  121.   /$57            {  push di             ;save this new psn}
  122.   /$89/$FE        {  mov  si,di          ;new char ptr}
  123.   /$46            {  inc  si             ;move from old char ptr}
  124.   /$FC            {  cld                 ;insure fwd}
  125.   /$F2/$A4        {  rep  movsb}
  126.   /$C6/$05/$B0    {  mov  byte [di],$B0  ;clear last char}
  127.   /$5F            {  pop  di             ;restore current psn}
  128.   /$5E            {  pop  si             ;restore str start}
  129.                   {BSShow:}
  130.   /$E8/$A0/$00    {  call ShowStr}
  131.   /$C3            {  ret}
  132.                   {NoBS:}
  133.   /$47            {   inc di             ;restore DI}
  134.   /$31/$C0        {   xor ax,ax          ;flag no cursor move}
  135.   /$C3            {   ret}
  136.                   
  137.                   {DnArrTst:}
  138.                   {;Down Arrow key goes straight down 1 line,}
  139.                   {;OR to last str char (+1 if not 255th char)}
  140.   /$3D/$00/$50    {  cmp  ax,$5000       ;down cursor?}
  141.   /$75/$06        {  jne  EndTst         ;nope}
  142.   /$03/$7E/$FA    {   add di,[bp-6]      ; + scr width = 1 line down}
  143.   /$72/$06        {   jc  End1           ; went beyond MAXINT}
  144.   /$C3            {    ret               ;  done}
  145.                   
  146.                   {EndTst:}
  147.                   {;End key goes to last str char (+1 if not 255th char)}
  148.   /$3D/$00/$4F    {  cmp  ax,$4F00       ;End key?}
  149.   /$75/$04        {  jne  UpArrTst       ;nope}
  150.                   {End1:}
  151.   /$BF/$FF/$FF    {   mov di,$FFFF       ; max out next char ptr}
  152.   /$C3            {   ret}
  153.                   
  154.                   {UpArrTst:}
  155.                   {;Up Arrow key goes straight up 1 line,}
  156.                   {;OR to first str char.}
  157.   /$3D/$00/$48    {  cmp  ax,$4800       ;up cursor?}
  158.   /$75/$06        {  jne  HomTst         ;nope}
  159.   /$2B/$7E/$FA    {   sub di,[bp-6]      ;- scr width = 1 line up}
  160.   /$72/$06        {   jb  DoHome         ;went negative, home}
  161.   /$C3            {    ret               ;done}
  162.                   
  163.                   {HomTst:}
  164.                   {;Home key goes to first str char.}
  165.   /$3D/$00/$47    {  cmp  ax,$4700       ;home key?}
  166.   /$75/$03        {  jne  InsTst         ;nope}
  167.                   {DoHome:}
  168.   /$31/$FF        {   xor  di,di         ; back to start}
  169.   /$C3            {   ret}
  170.                   
  171.                   {InsTst:}
  172.                   {;Insert key toggles insert/overwrite mode}
  173.   /$3D/$00/$52    {  cmp  ax,$5200       ;Insert key?}
  174.   /$75/$06        {  jne  CrTst          ;nope}
  175.   /$F6/$56/$F9    {   not byte [bp-7]    ;reverse all the bits}
  176.   /$31/$C0        {   xor ax,ax          ;no cursor updating}
  177.   /$C3            {   ret}
  178.                   
  179.                   {CrTst:}
  180.                   {;Return or ^Z terminate input, exit procedure.}
  181.   /$3D/$0D/$1C    {  cmp  ax,$1C0D       ;Is it a CR?}
  182.   /$74/$4C        {  je   GetKeyX        ;yep, done}
  183.   /$3D/$1A/$2C    {   cmp ax,$2C1A       ; how about ^Z}
  184.   /$75/$04        {   jne FunTst         ; nope}
  185.   /$B8/$0D/$1C    {    mov ax,$1C0D      ;  force to CR}
  186.   /$C3            {    ret}
  187.                   
  188.                   {FunTst:}
  189.                   {;We gobble any other function or cursor keys}
  190.                   {;so spurious chars won't get in the string.}
  191.   /$30/$E4        {  xor ah,ah           ;clear msb (aux byte)}
  192.   /$08/$C0        {  or  al,al           ;is it a special? (cursor/function)}
  193.   /$74/$3D        {  je  GetKeyX         ;yep, ignore it (AX=0)}
  194.                   
  195.                   {;We assume it's a legal char now, so we display it.}
  196.                   {;Legals include other control keys.}
  197.                   {;v1.5}
  198.                   {; If insert mode, we must first move the string right 1}
  199.                   {; from current char (losing chars beyond 255th).}
  200.                   
  201.                   {PrChr:}
  202.   /$80/$7E/$F9/$00{  cmp  byte [bp-7],0  ;overwrite mode?}
  203.   /$74/$32        {  jz   PrC            ;yep, just stuff it}
  204.                   
  205.   /$50            {  push ax             ;save current char}
  206.   /$E8/$A4/$00    {  call FixLen         ;CX=current length,AX=rel psn}
  207.   /$29/$C1        {  sub  cx,ax          ;length - cur psn = chars to move}
  208.   /$58            {  pop  ax             ;restore char}
  209.   /$72/$29        {  jb   PrC            ;curr char is next char (empty), stuff it}
  210.   /$75/$12        {  jnz  Pr1            ;more than 1 char to move}
  211.                   {;We're sitting on last real char,}
  212.                   {;so just 1 to move to right.  Do it manually:}
  213.   /$8A/$25        {   mov ah,[di]        ; snarf old char}
  214.   /$50            {   push ax            ; save}
  215.   /$E8/$21/$00    {   call PrC           ; display,stuff}
  216.   /$E8/$6E/$00    {   call AbsCur        ; doublecheck psn, DI, etc.}
  217.   /$58            {   pop ax             ; get back char}
  218.   /$88/$E0        {   mov al,ah          ; old char into AL}
  219.   /$80/$F9/$FF    {   cmp cl,255         ; length maxed out?}
  220.   /$72/$16        {   jb  PrC            ; nope, stuff it and return}
  221.   /$C3            {    ret               ;  gobble last char}
  222.                   
  223.                   {Pr1:}
  224.   /$56            {  push si             ;save str start}
  225.   /$57            {  push di             ;save this new psn}
  226.   /$41            {  inc  cx             ;adjust chars to move}
  227.   /$01/$CF        {  add  di,cx          ;curr char + chars to move}
  228.                   {;di points to last char in string}
  229.   /$89/$FE        {  mov  si,di          ;same place}
  230.   /$4E            {  dec  si             ;back up to char before}
  231.   /$FD            {  std                 ;insure backward}
  232.   /$F2/$A4        {  rep  movsb          ;do the move DI-1 to DI}
  233.   /$FC            {  cld                 ;be neat: forward again}
  234.   /$5F            {  pop  di             ;restore current psn}
  235.   /$5E            {  pop  si             ;restore str start}
  236.   /$AA            {  stosb               ;stuff ASCII char, bump DI}
  237.   /$E8/$20/$00    {  call ShowStr        ;display the string (AX=0)}
  238.   /$F7/$D0        {  not  ax             ;AX <> 0,flag cursor updating}
  239.   /$C3            {  ret}
  240.                   
  241.                   {PrC:}
  242.   /$AA            {  stosb               ;stuff ASCII char, bump DI}
  243.   /$B4/$0E        {  mov  ah,$0E         ;write char TTY}
  244.   /$CD/$10        {  int  $10            ;BIOS}
  245.                   {GetKeyX:}
  246.   /$C3            {  ret}
  247.                   
  248.                   {PadStr:}
  249.                   {;Pads from past last char to 255 chars with graphic char.}
  250.                   {;Displays str, homes cursor.}
  251.                   {;Returns CX=str length, DI=str start}
  252.                   
  253.   /$30/$ED        {  xor  ch,ch          ;clear msb}
  254.   /$8A/$0C        {  mov  cl,[si]        ;get str length}
  255.   /$89/$F7        {  mov  di,si          ;current char = str start}
  256.   /$47            {  inc  di             ;bump past len byte}
  257.   /$56            {  push si             ;str start}
  258.   /$57            {  push di             ;and next char ptr}
  259.                   
  260.   /$01/$CF        {  add  di,cx          ;add in length (if any)}
  261.   /$F6/$D1        {  not  cl             ;255-str len}
  262.   /$B0/$B0        {  mov  al,$B0         ;pad with graphic char}
  263.   /$FC            {  cld                 ;insure fwd (sigh...)}
  264.   /$F2/$AA        {  rep  stosb          ;do the pad}
  265.   /$5F            {  pop  di             ;restore str start}
  266.   /$5E            {  pop  si             ;and next char ptr}
  267.   /$8B/$56/$FC    {  mov dx,[bp-4]       ;home cursor to str start}
  268.                   {;fall thru to ShowStr and return}
  269.                   
  270.                   {ShowStr:}
  271.                   {;Display str at starting coordinates,}
  272.                   {;Clear to EOL (e.g., full 255 chars).}
  273.                   {;Exit with CX=current str length, DI unchanged,}
  274.                   {; cursor psn unchanged.}
  275.   /$52            {  push dx             ;remember current cursor psn}
  276.   /$B4/$03        {  mov  ah,3           ;read cur psn (want cursor size)}
  277.   /$CD/$10        {  int  $10            ;BIOS CX = current cursor size}
  278.                   
  279.   /$51            {  push cx             ;save cursor size}
  280.   /$B5/$20        {  mov  ch,$20         ;turn cursor off}
  281.   /$B4/$01        {  mov  ah,1           ;set cursor size}
  282.   /$CD/$10        {  int  $10            ;BIOS}
  283.   /$8B/$56/$FC    {  mov  dx,[bp-4]      ;home cursor to str start}
  284.   /$B4/$02        {  mov  ah,2           ;position cursor}
  285.   /$CD/$10        {  int  $10            ;BIOS}
  286.                   
  287.                   {;We display all 255 chars. Str buffer may be padded}
  288.                   {;with graphic chars (not part of real length),}
  289.                   {;but we show them to "Clr EOL".}
  290.   /$56            {  push si             ;str start}
  291.   /$46            {  inc  si             ;bump past length byte}
  292.   /$B9/$FF/$00    {  mov  cx,255         ;255 chars}
  293.   /$B4/$0E        {  mov  ah,$0E         ;BIOS display char TTY}
  294.   /$FC            {  cld                 ;insure forward}
  295.                   {SL1:}
  296.   /$AC            {  lodsb               ;next string char}
  297.   /$CD/$10        {  int  $10            ;display it}
  298.   /$E2/$FB        {  loop SL1            ;do them all}
  299.   /$5E            {  pop  si             ;restore str start}
  300.                   
  301.   /$59            {  pop  cx             ;old cursor size}
  302.                   
  303.   /$B4/$01        {  mov  ah,1           ;set cursor size}
  304.   /$CD/$10        {  int  $10            ;BIOS}
  305.   /$5A            {  pop  dx             ;old cursor psn}
  306.   /$B4/$02        {  mov  ah,2           ;set cursor psn}
  307.   /$CD/$10        {  int  $10            ;BIOS}
  308.   /$E8/$4C/$00    {  call GetLen         ;update CX=len}
  309.   /$88/$0C        {  mov  [si],cl        ;and force into len byte}
  310.   /$31/$C0        {  xor  ax,ax          ;so we don't call AbsCur}
  311.   /$C3            {  ret}
  312.                   
  313.                   {AbsCur:}
  314.                   {;Absolute cursor movement to next char ptr (DI).}
  315.                   {;Enter with DI = ptr to next str char.}
  316.                   {;Test to insure DI doesn't point beyond}
  317.                   {; 255 chars past start (from FixLen)}
  318.                   {;Exit with}
  319.                   {; DX= adjusted xy coords}
  320.                   {; DI = adjusted current char ptr (from FixLen)}
  321.                   {; CX = str length (from GetLen)}
  322.                   {; cursor pointing to next str char}
  323.                   
  324.   /$8B/$56/$FC    {  mov  dx,[bp-4]      ;get str's starting cursor psn}
  325.   /$E8/$20/$00    {  call FixLen         ;check str len,char ptr}
  326.                   {;Returns CX=str len, AX=next char ofs}
  327.   /$09/$C0        {  or  ax,ax           ;curr char = start?}
  328.   /$74/$17        {  je  PsnCur          ;yep, go "home" cursor}
  329.                   
  330.   /$48            {  dec  ax}
  331.   /$51            {  push cx             ;save str len}
  332.   /$8B/$4E/$FA    {  mov  cx,[bp-6]      ;get scr width}
  333.   /$00/$D0        {  add  al,dl          ;add in starting col}
  334.   /$80/$D4/$00    {  adc  ah,0           ;in case of carry}
  335.                   {AL1:}
  336.   /$39/$C8        {  cmp  ax,cx          ;less than 1 line?}
  337.   /$76/$06        {  jbe  A3             ;yep}
  338.   /$29/$C8        {   sub ax,cx          ;>width, subtract width}
  339.   /$FE/$C6        {   inc  dh            ;bump row}
  340.   /$EB/$F6        {   jmp short AL1      ;until col < = width}
  341.                   {A3:                   ;updated DL=col,DH=row}
  342.   /$59            {  pop  cx             ;restore length}
  343.   /$88/$C2        {  mov  dl,al          ;update row}
  344.                   
  345.                   {PsnCur:}
  346.   /$B4/$02        {  mov  ah,2           ;svc 2, position cursor}
  347.   /$CD/$10        {  int  $10            ;BIOS}
  348.   /$C3            {  ret}
  349.                   
  350.                   {FixLen:}
  351.                   {;Insures str len (and CX) are legal,}
  352.                   {;keeps DI within legal limits (start + 0..254)}
  353.                   {;Enters with DI = current char ptr (could be beyond str length),}
  354.                   {;Exits with CX = str len, AX=rel cursor psn within string}
  355.                   
  356.                   {;first scan for our terminating $B0 graphics char}
  357.   /$E8/$1E/$00    {  call GetLen         ;returns with CX=len}
  358.   /$E3/$06        {  jcxz F0             ;no str length, force to start}
  359.                   {;now insure str ptr is legal (within string)}
  360.   /$89/$F8        {  mov  ax,di          ;str ptr}
  361.   /$29/$F0        {  sub  ax,si          ;- str start = next char ofs}
  362.   /$77/$06        {  ja   F1             ;ok, next char > start}
  363.                   {F0:}
  364.   /$31/$C0        {   xor ax,ax          ; next char ofs = 0}
  365.   /$89/$F7        {   mov di,si          ; force next char to start}
  366.   /$47            {   inc di             ; bump to 1st char}
  367.   /$C3            {   ret                ; done}
  368.                   
  369.                   {;at or above 1st char, how about beyond str end?}
  370.                   {F1:}
  371.   /$39/$C8        {  cmp  ax,cx          ;< len?}
  372.   /$76/$0B        {  jbe  F2             ;yep}
  373.   /$89/$F7        {   mov  di,si         ; start}
  374.   /$89/$C8        {   mov  ax,cx         ; get length}
  375.   /$3C/$FF        {   cmp  al,255        ; maxed out?}
  376.   /$74/$01        {   je   F1A           ; yep}
  377.   /$40            {    inc  ax           ;  no, so bump to next char}
  378.                   {F1A:}
  379.   /$01/$C7        {   add  di,ax         ; point to last char}
  380.                   {F2:}
  381.   /$C3            {  ret}
  382.                   
  383.                   {GetLen:}
  384.   /$57            {  push di             ;save next char ptr}
  385.   /$89/$F7        {  mov  di,si          ;start}
  386.   /$B9/$FF/$00    {  mov  cx,255         ;max possible len}
  387.   /$01/$CF        {  add  di,cx          ;point to end}
  388.   /$FD            {  std                 ;scan backwards}
  389.   /$B0/$B0        {  mov  al,$B0         ;graphics char ends it}
  390.   /$F3/$AE        {  repe scasb          ;scan until we run out of $B0's}
  391.   /$FC            {  cld}
  392.                   {;CX points to the non-$B0 char (or 0)}
  393.   /$74/$01        {  jz G1               ;didn't find ANY}
  394.   /$41            {   inc cx             ; adjust from the scasb}
  395.                   {G1:}
  396.   /$5F            {  pop  di             ;restore next char ptr}
  397.   /$C3            {  ret                 ;with CX=len}
  398.                   
  399.                   {InitScr:}
  400.                   {;Get required screen stuff}
  401.   /$B4/$0F        {  mov  ah,$0F         ;get current video mode}
  402.   /$CD/$10        {  int  $10            ;BIOS}
  403.                   {;BH = active display page (protect it!)}
  404.   /$88/$E0        {  mov  al,ah          ;need width as LSB}
  405.   /$30/$E4        {  xor  ah,ah          ;clear msb}
  406.   /$89/$46/$FA    {  mov  [bp-6],ax      ;save current scr width}
  407.                   
  408.                   {;We need 255 chars of screen space WITHOUT SCROLLING,}
  409.                   {;or our cursor positioning will be screwed up.}
  410.                   {;Test now to see if we have enough room.}
  411.                   {;If not, do our scrolling NOW instead of letting BIOS do it.}
  412.                   
  413.   /$89/$C6        {  mov  si,ax          ;save width in SI}
  414.   /$B4/$03        {  mov  ah,3           ;get current cursor psn in DX}
  415.   /$CD/$10        {  int  $10            ;BIOS}
  416.   /$80/$FE/$15    {  cmp  dh,21          ;row 21 or less?}
  417.   /$76/$25        {  jbe  NoScroll       ;yep, scroll testing}
  418.                   
  419.   /$88/$F0        {  mov  al,dh          ;current row}
  420.   /$89/$F1        {  mov  cx,si          ;CL = width multiplier}
  421.   /$F6/$E1        {  mul  cl             ;AX=row * width}
  422.                   {C1:}
  423.   /$00/$D0        {  add  al,dl          ;add in current col}
  424.   /$80/$D4/$00    {  adc  ah,0           ;in case of carry}
  425.   /$89/$C1        {  mov  cx,ax          ;remember as abs scr psn}
  426.   /$05/$FF/$00    {  add  ax,255         ;plus full line length}
  427.   /$89/$C7        {  mov  di,ax          ;abs scrn psn + string}
  428.                   {CL1:}
  429.   /$39/$CF        {  cmp  di,cx          ;less than 1 line?}
  430.   /$76/$0B        {  jbe  CDone          ;yep, ok}
  431.   /$B8/$0A/$0E    {   mov  ax,$0E0A      ; display LF via BIOS}
  432.   /$CD/$10        {   int  $10           ; BIOS}
  433.   /$29/$F7        {   sub  di,si         ; subtract width}
  434.   /$FE/$CE        {   dec  dh            ; back up 1 row}
  435.   /$EB/$F1        {   jmp short CL1}
  436.                   {CDone:}
  437.   /$B4/$02        {  mov  ah,2           ;svc 2, position cursor}
  438.   /$CD/$10        {  int  $10            ;BIOS}
  439.                   {NoScroll:}
  440.   /$89/$56/$FC    {  mov  [bp-4],dx      ;now save current cursor psn}
  441.                   
  442.                   {;Get screen attributes at current cursor psn}
  443.   /$B4/$08        {  mov  ah,8           ;Read char & attrib}
  444.   /$CD/$10        {  int  $10            ;BIOS}
  445.   /$88/$E3        {  mov  bl,ah}
  446.                   {;BL = screen attribute (protect it!)}
  447.   /$C3            {  ret}
  448.                   
  449.                   {Done:}
  450.   /$1F            {  pop  DS             ;restore DS}
  451.                   {;let Turbo do the rest}
  452. );
  453.   END;  {of ToadLn}
  454.