home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / CEXPRESS.ZIP / KEYBOARD.ASM / EDITLINE.ASM < prev    next >
Assembly Source File  |  1989-05-03  |  13KB  |  462 lines

  1. ;void edit_line(return_string,col,row,color,max_len,st,esc,ext,ch_case);
  2. ;  unsigned char  *return_string,col,row,color,max_len,st,est,ext,ch_case;
  3.  
  4.     EXTRN  _memory_model:byte
  5.     EXTRN  _error_code:byte
  6.     EXTRN  _beep_on:byte
  7.  
  8. _TEXT    SEGMENT BYTE PUBLIC 'CODE'
  9.     ASSUME CS:_TEXT
  10.     PUBLIC _edit_line
  11. _edit_line proc near
  12.     push bp            ;
  13.     mov  bp,sp        ;
  14.     push di            ;
  15.     push si            ;
  16.     cmp  _memory_model,0    ;near or far?
  17.     jle  begin        ;jump if near
  18.     inc  bp            ;else add 2 to BP
  19.     inc  bp            ;
  20. begin:    push ds            ;
  21.     jmp  A5            ;jump over data
  22. EscapeCode db ?            ;holds escape code or zero
  23. ExtendedCode db ?        ;same
  24. DeleteCase db 0            ;flags that Del or Backspc key hit
  25. beepon db ?            ;keeps _beep_on parameter
  26. LeftLimit  db ?            ;left cursor limit on screen
  27. RightLimit db ?            ;right cursor limit
  28. Case  db  ?            ;flags kind of case change
  29. CaseChange db ?            ;flags whether case change
  30. Max_Len    db ?            ;holds MaxLen parameter
  31. StringEnd db ?            ;col of last char of string
  32. errorcode  db ?            ;holds return code
  33. StringPos db ?            ;pts to string variable = cursor pos
  34.  
  35. Beep    PROC 
  36.     push dx            ;save cursor ptr
  37.     cmp  cs:beepon,0    ;beep on?
  38.     jz   A1            ;jump if not
  39.     mov  dl,7        ;beep char
  40.     mov  ah,2        ;DOS function to write char
  41.     int  21h        ;make the beep
  42. A1:    pop  dx            ;
  43.     ret
  44. Beep    ENDP
  45.  
  46. DisplayChars PROC        ;writes changed char string on screen
  47.     or   di,di        ;zero chars to write?
  48.     jz   A3            ;
  49. A2:    mov  ah,2        ;function to set cursor
  50.     mov  bh,0        ;page
  51.     int  10h        ;    
  52.     mov  al,[si]        ;get char
  53.     mov  bl,[bp+10]        ;attribute
  54.     mov  bh,0        ;page
  55.     mov  cx,1        ;number chars to write
  56.     mov  ah,9        ;function number
  57.     int  10h        ;
  58.     inc  si            ;forward string ptr    
  59.     inc  dl            ;forward cursor ptr
  60.     dec  di            ;loop till all chars shifted
  61.     jnz  A2            ;
  62.     cmp  cs:DeleteCase,1    ;
  63.     jne  A4            ;
  64. A3:    mov  cs:DeleteCase,0    ;
  65.     mov  byte ptr[si],' '   ;
  66.     inc  di            ;through loop once more
  67.     jmp  short A2        ;go write space at end of string
  68. A4:    ret
  69. DisplayChars ENDP
  70.  
  71. A5:    mov  bl,_beep_on    ;get _beep_on value
  72.     mov  cs:beepon,bl    ;keep in local variable
  73.     cmp  _memory_model,2    ;data near or far?
  74.     jb   L1            ;
  75.     lds  si,dword ptr[bp+4] ;DS:SI pts to Strg
  76.     les  di,dword ptr[bp+4] ;ES:DI too
  77.     inc  bp            ;add 2 to BP since dword ptr
  78.     inc  bp            ;
  79.     jmp  short L2        ;
  80. L1:    mov  ax,ds        ;ES = DS
  81.     mov  es,ax        ;
  82.     mov  si,[bp+4]        ;
  83.     mov  di,si        ;
  84. L2:    cmp  byte ptr[si],0    ;test for null string
  85.     je   L4            ;if not null, change to Pascal string
  86.     mov  cx,255        ;max string length
  87.     sub  al,al        ;seek terminating null
  88.     repne scasb        ;
  89.     dec  di            ;point to null
  90.     mov  cx,di        ;calculate number bytes
  91.     sub  cx,si        ;
  92.     mov  ah,cl        ;keep string length
  93.     dec  di            ;point to last ptr of string
  94. L3:    mov  al,es:[di]        ;shift the chars
  95.     mov  es:[di+1],al    ;
  96.     dec  di            ;
  97.     loop L3            ;
  98.     mov  [si],ah        ;
  99.     mov  di,si        ;reset DI    
  100. L4:    mov  cs:errorcode,0    ;default return code
  101.     mov  cs:ExtendedCode,0    ;
  102.     mov  cs:EscapeCode,0    ;
  103.     mov  al,[bp+18]        ;Ext
  104.     mov  bl,[bp+16]        ;Esc
  105.     cmp  al,0        ;escape char is extended code?
  106.     jz   A6            ;
  107.     mov  cs:EscapeCode,bl    ;ASCII code
  108.     jmp  short A7        ;
  109. A6:    mov  cs:ExtendedCode,bl    ;
  110.  
  111. ;---Figure out character case:
  112. A7:    mov  al,[bp+20]        ;get CharCase
  113.     mov  cs:CaseChange,0    ;flags no case change
  114.     cmp  al,97        ;lower case?
  115.     jb   A8            ;jump if not
  116.     sub  al,32        ;make uppercase
  117. A8:    cmp  al,'U'        ;specify uppercase?
  118.     jne  A9            ;
  119.     mov  cs:Case,1        ;uppercase
  120.     inc  cs:CaseChange    ;1 = case change made
  121.     jmp  short A0        ;
  122. A9:    cmp  al,'L'        ;specify lowercase?
  123.     jne  A0            ;
  124.     mov  cs:Case,0        ;lowercase
  125.     inc  cs:CaseChange    ;1 = case change made
  126.  
  127. ;---Initialize parameters:
  128. A0:    mov  dh,[bp+8]        ;get Row
  129.     or   dh,dh        ;zero?
  130.     jz   B1            ;quit if so
  131.     dec  dh            ;count from zero
  132.     mov  dl,[bp+6]        ;get Col
  133.     or   dl,dl        ;zero?
  134.     jz   B1            ;quit if so
  135.     dec  dl            ;count from zero
  136.     mov  cs:LeftLimit,dl    ;set LeftLimit
  137.     mov  al,dl        ;copy
  138.     mov  ah,[bp+12]        ;get MaxLen
  139.     mov  cs:Max_Len,ah    ;copy
  140.     or   ah,ah        ;zero?
  141.     jnz  B2            ;jump ahead if not
  142. B1:    jmp  F4            ;quit
  143. B2:    add  al,ah        ;figure RightLimit
  144.     dec  al            ;
  145.     mov  cs:RightLimit,al    ;
  146.     mov  al,[si]        ;get string length
  147.     cmp  al,cs:max_len    ;
  148.     jna  B3            ;quit if too long
  149.     mov  cs:errorcode,1    ;1 = string too long
  150.     jmp  short B1        ;quit
  151. B3:    mov  bl,al        ;copy strg len
  152.     add  bl,dl        ;add Col offset
  153.     dec  bl            ;count from zero
  154.     mov  cs:StringEnd,bl    ;save col pos of end of string
  155.     mov  bl,[bp+14]        ;get cursor start pos
  156.     inc  bl            ;adjust to count from 1
  157.     mov  cs:StringPos,bl    ;save
  158.     or   bl,bl        ;zero?
  159.     jz   B5            ;then assume 1
  160.     cmp  bl,al        ;start pos in string?
  161.     jna  B4            ;jump if so
  162.     mov  bl,al        ;else set to char after end of string
  163.     inc  bl            ;
  164.     mov  cs:StringPos,bl    ;
  165. B4:     dec  bl            ;count from zero
  166.     add  dl,bl        ;add to start col
  167.     cmp  dl,cs:RightLimit    ;cursor in field?
  168.     ja   B1            ;out or range error if not
  169. B5:    mov  ah,2        ;function to set cursor
  170.     mov  bh,0        ;page number
  171.     int  10h        ;set the cursor
  172.  
  173. ;---Ready to go, get keystroke:
  174. B6:    mov  di,si        ;Ctrl-cursor moves change DI
  175.     mov  ah,7        ;DOS function to get keystroke
  176.     int  21h        ;
  177.     or   al,al        ;extended code?
  178.     jz   B7            ;
  179.     jmp  D6            ;jump ahead if not extended
  180. B7:    mov  ah,7        ;get extended code
  181.     int  21h        ;
  182.     mov  bl,cs:ExtendedCode    ;test for escape char
  183.     or   bl,bl        ;zero = escape not extended code
  184.     jz   B8            ;
  185.     cmp  bl,al        ;the code?
  186.     jne  B8            ;
  187.     mov  cs:errorcode,2    ;
  188.     jmp  F4            ;quit
  189. B8:    cmp  al,75        ;cursor-left
  190.     jne  C1            ;
  191.     cmp  dl,cs:LeftLimit    ;cursor against left margin?
  192.     je   B0            ;
  193.     dec  dl            ;dec cursor ptr
  194.     dec  cs:StringPos    ;dec string ptr
  195. B9:    mov  ah,2        ;func to set cursor
  196.     mov  bh,0        ;page
  197.     int  10h        ;move cursor
  198.     jmp  short B6        ;
  199. B0:    call beep        ;
  200.     jmp  short B6        ;go get next key
  201. C1:    cmp  al,77        ;cursor-right
  202.     jne  C3            ;
  203.     cmp  dl,cs:RightLimit    ;cursor against right margin?
  204.     je   B0            ;beep if so
  205.     mov  al,cs:StringEnd    ;don't let go beyond space after last char
  206.     cmp  al,255        ;can't move cursor if null string
  207.     je   B0            ;
  208.     cmp  dl,al        ;
  209.     ja   B0            ;
  210. C2:    inc  dl            ;inc cursor ptr
  211.     inc  cs:StringPos    ;inc string ptr
  212.     jmp  short B9        ;go move cursor
  213. C3:    cmp  al,115        ;Ctrl cursor-left
  214.     jne  C7            ;
  215.     cmp  dl,cs:LeftLimit    ;cursor against left margin?
  216.     je   B0            ;
  217.     sub  cx,cx        ;
  218.     mov  cl,cs:StringPos    ;offset of cursor in string
  219.     dec  cx            ;adjust
  220.     std            ;will scan backwards
  221.     add  di,cx        ;
  222.     mov  al,' '        ;seek space char
  223.     cmp  byte ptr es:[di],' ' ;at first char of word?
  224.     je   C5            ;jump if so
  225. C4:    repne scasb        ;
  226.     jnz  C6            ;jump if not found
  227.     add  cx,2        ;new position
  228.     mov  cs:StringPos,cl    ;set string ptr
  229.     mov  dl,cs:LeftLimit    ;
  230.     add  dl,cl        ;
  231.     dec  dl            ;
  232.     jmp  short B9        ;go set cursor
  233. C5:    mov  al,' '        ;
  234.     repe scasb        ;seek first non-space char
  235.     jz   C6            ;jump if not found
  236.     jmp  short C4        ;now find start of next word
  237. C6:    mov  cs:StringPos,1    ;
  238.     mov  dl,cs:LeftLimit    ;
  239.     jmp  short B9        ;
  240. C7:    cmp  al,116        ;Ctrl cursor-right
  241.     jne  D3            ;
  242.     cmp  dl,cs:RightLimit    ;cursor against left margin?
  243.     je   B0            ;
  244.     mov  al,cs:StringEnd    ;cursor at last char?
  245.     cmp  dl,al        ;
  246.     jne  C8            ;
  247. C8:    inc  al            ;
  248.     cmp  dl,al        ;
  249.     jne  C9            ;
  250.     jmp  B0            ;
  251. C9:    sub  cx,cx        ;
  252.     mov  cl,es:[di]        ;get string length
  253.     sub  ax,ax        ;figure number chars to scan
  254.     mov  al,cs:StringPos    ;
  255.     sub  cl,al        ;
  256.     mov  bx,cx        ;keep copy
  257.     cld            ;scan forward
  258.     add  di,ax        ;set string ptr
  259.     inc  di            ;
  260.     mov  al,' '        ;seek space char
  261.     cmp  byte ptr es:[di],' ' ;at space char?
  262.     jne  C0            ;
  263.     cmp  byte ptr es:[di-1],' ' ;prior char a space?
  264.     je   C9B        ;if not, run through all spaces 
  265.     jmp  C2            ;otherwise, just forward cursor 1 col
  266. C9B:    mov  al,' '        ;
  267.     repe scasb        ;seek first non-space char
  268.     jz   D1            ;jump if not found
  269. C0:    repne scasb        ;
  270.     jnz  D1            ;jump if not found
  271.     sub  bx,cx        ;number chars traversed
  272.     add  dl,bl        ;forward cursor ptr
  273.     add  cs:StringPos,bl    ;forward string ptr
  274.     jmp  B9            ;go set cursor
  275. D1:    mov  al,[si]        ;place cursor at end of string
  276.     cmp  al,cs:Max_Len    ;
  277.     je   D2            ;
  278.     inc  al            ;
  279. D2:    mov  cs:StringPos,al    ;
  280.     mov  dl,cs:LeftLimit    ;figure cursor position
  281.     add  dl,al        ;
  282.     dec  dl            ;
  283.     jmp  B9            ;
  284. D3:    cmp  al,83        ;Del key?
  285.     jne  D5            ;
  286.     mov  al,[si]        ;is there a char above the cursor?
  287.     cmp  cs:StringPos,al    ;
  288.     jna  D4            ;jump if so
  289.     call beep        ;beep
  290.     jmp  B6            ;go get next key
  291. D4:    jmp  E2            ;go join Backspace routine
  292. D5:    jmp  B6            ;go get next key
  293. D6:    mov  bl,cs:EscapeCode    ;test for escape char
  294.     or   bl,bl        ;zero = escape not extended code
  295.     jz   D7            ;
  296.     cmp  bl,al        ;the code?
  297.     jne  D7            ;
  298.     mov  cs:errorcode,2    ;
  299.     jmp  F4            ;quit
  300.  
  301. ;---Make case change if required:
  302. D7:    cmp  cs:CaseChange,0    ;case change required?
  303.     je   D9            ;jump ahead if not
  304.     cmp  cs:Case,0        ;all lowercase?
  305.     jne  D8            ;jump if not
  306.     cmp  al,65        ;see if uppercase
  307.     jb   D9            ;
  308.     cmp  al,90        ;
  309.     ja   D9            ;
  310.     add  al,32        ;convert
  311.     jmp  short D9        ;
  312. D8:    cmp  al,97        ;see if lowercase
  313.     jb   D9            ;
  314.     cmp  al,122        ;
  315.     ja   D9            ;
  316.     sub  al,32        ;convert
  317.  
  318. ;---Intercept CARRIAGE RETURN:
  319. D9:    cmp  al,13        ;Carriage Return?
  320.     jne  D0            ;jump if not
  321.     jmp  F4            ;go quit
  322.  
  323. ;---Intercept BACKSPACE:
  324. D0:    cmp  al,8        ;backspace?
  325.     jne  E6            ;jump if not
  326.     cmp  dl,cs:LeftLimit    ;cursor at start of line?
  327.     jne  E1            ;jump if room for backspace
  328.     call beep        ;else beep
  329.     jmp  short E5        ;
  330. E1:    dec  dl            ;move cursor ptr to prior char
  331.     dec  cs:StringPos    ;dec string ptr
  332.  
  333. ;---For DEL or backspace, remove char from string:
  334. E2:    sub  ax,ax        ;pt SI to char to be removed
  335.     mov  cx,ax        ;
  336.     mov  cl,[si]        ;string length
  337.     mov  al,cs:StringPos    ;
  338.     sub  cx,ax        ;number characters to shift
  339.     or   cx,cx        ;
  340.     jz   E4            ;
  341.     add  si,ax        ;
  342. E3:    mov  al,[si+1]        ;get next char
  343.     mov  [si],al        ;shift
  344.     inc  si            ;next
  345.     loop E3            ;
  346.     mov  si,di        ;move SI back to descriptor
  347. E4:    dec  byte ptr[si]    ;dec descriptor
  348.  
  349. ;---Write the new string:
  350.     mov  cs:DeleteCase,1    ;flag that deleting char
  351.     sub  ax,ax        ;clear AX
  352.     mov  al,[si]        ;get string length
  353.     sub  al,cs:StringPos    ;figure length
  354.     inc  al            ;number chars to display
  355.     sub  cx,cx        ;
  356.     mov  cl,cs:StringPos    ;
  357.     add  si,cx        ;
  358.     push di            ;need DI as counter
  359.     mov  di,ax        ;
  360.     push dx            ;save cursor position
  361.     call DisplayChars    ;
  362.     dec  cs:StringEnd    ;
  363.     pop  dx            ;
  364.     mov  ah,2        ;set cursor
  365.     mov  bh,0        ;
  366.     int  10h        ;
  367.     pop  di            ;start of string ptr
  368.     mov  si,di        ;
  369. E5:    jmp  B6            ;go get next key
  370. E6:    cmp  al,31        ;reject all other control codes
  371.     ja   E7            ;
  372.     call beep        ;
  373.     jmp  B6            ;go get next key
  374.  
  375. ;---Add a character to the data string:
  376. E7:    mov  bl,[si]        ;get string length
  377.     cmp  bl,cs:Max_len    ;in range?
  378.     jne  E8            ;jump ahead if OK
  379.     call Beep        ;go beep
  380.     jmp  B6            ;go get next keystroke
  381. E8:    push ax            ;save input char
  382.     sub  ax,ax        ;point SI to end of string
  383.     mov  al,[si]        ;
  384.     or   ax,ax        ;if null, point to first byte
  385.     jnz  E9            ;
  386.     inc  ax            ;
  387. E9:    add  si,ax        ;
  388.     mov  cl,cs:StringEnd    ;does cursor follow last char?
  389.     cmp  dl,cl        ;
  390.     jna  E0            ;jump if not
  391.     cmp  dl,cs:LeftLimit    ;special case when starting will null strg
  392.     jne  F2            ;
  393. E0:    sub  cl,dl        ;number chars
  394.     inc  cl            ;      to shift
  395.     sub  ch,ch        ;extend to word
  396.     or  cx,cx        ;test for zero length
  397.     jnz  F1            ;jump ahead if nonzero
  398.     dec  si            ;pull back pointer
  399.     jmp  short F2        ;skip character shift
  400. F1:    mov  al,[si]        ;shift the string segment
  401.     mov  [si+1],al        ;
  402.     dec  si            ;
  403.     loop F1            ;
  404. F2:    pop  ax            ;fetch input char
  405.     inc  si            ;back to cursor position
  406.     mov  [si],al        ;insert new char
  407.     mov  si,di        ;si back to start of string
  408.     inc  byte ptr[si]    ;inc string descriptor
  409.     inc  cs:StringEnd    ;forward end-of-strg col ptr
  410.     inc  cs:StringPos    ;forward string position ptr
  411.     inc  dl            ;forward cursor ptr
  412.  
  413. ;---Now rewrite portion of string on display:
  414.     mov  cs:DeleteCase,0    ;flag DisplayChars that not Del case
  415.         sub  cx,cx        ;figure offset in data string
  416.     mov  bx,cx        ;
  417.     mov  cl,[si]        ;get string length
  418.     mov  bl,cs:StringPos    ;
  419.     sub  cx,bx        ;equals number chars to write - 2
  420.     add  cx,2        ;
  421.     add  si,bx        ;set string ptr
  422.     dec  si            ;
  423.     push di            ;need DI as counter
  424.     mov  di,cx        ;
  425.     push dx            ;save cursor position
  426.     dec  dl            ;pull back cursor
  427.     call DisplayChars    ;go write chars
  428.     pop  dx            ;restore cursor pos
  429.     cmp  dl,cs:RightLimit    ;don't push cursor beyond MaxLen
  430.     jna  F3            ;
  431.     dec  dl            ;
  432.     dec  cs:StringPos    ;
  433. F3:    mov  ah,2        ;
  434.     mov  bh,0        ;
  435.     int  10h        ;
  436.     pop  di            ;
  437.     mov  si,di        ;point SI back to string descriptor
  438.     jmp  B6            ;go do next keystroke
  439.  
  440. ;---Exit code:
  441. F4:    mov  al,cs:errorcode    ;set errorcode
  442.     pop  ds            ;
  443.     mov  _error_code,al    ;
  444.     sub  cx,cx        ;change to C string
  445.     mov  cl,[si]        ;get string length
  446.     jcxz F6            ;quit if null
  447. F5:    inc  si            ;
  448.     mov  al,[si]        ;
  449.     mov  [si-1],al        ;
  450.     loop F5            ;
  451.     mov  byte ptr [si],0    ;null terminator
  452. F6:    pop  si            ;
  453.     pop  di            ;
  454.     pop  bp            ;
  455.     cmp  _memory_model,0    ;quit
  456.     jle  quit        ;
  457.     db   0CBh        ;RET far
  458. quit:    ret            ;RET near
  459. _edit_line ENDP
  460. _TEXT    ENDS
  461.     END
  462.