home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / turbopas / toadln5.arc / TOADLN5.ASM < prev    next >
Assembly Source File  |  1988-08-24  |  14KB  |  448 lines

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