home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / ALIV11.ZIP / KEYSTRIN.ASM < prev    next >
Assembly Source File  |  1988-03-21  |  38KB  |  1,966 lines

  1. ;
  2. ; KEYSTRIN.ASM
  3. ;
  4. ; A DYNLINK LIBRARY KBD REPLACEMENT SUBSYSTEM ALLOWING COMMAND RECALL,
  5. ;    LINE EDITING, AND ALIAS REPLACEMENT.
  6. ;
  7.  
  8.     TITLE    KEYSTRIN
  9.  
  10.     .286P
  11.  
  12. EXTRN    DOSDEVIOCTL:FAR, DOSOPEN:FAR, DOSCLOSE:FAR, DOSBEEP:FAR
  13. EXTRN    DOSWRITE:FAR, DOSGETINFOSEG:FAR, KBDGETSTATUS:FAR
  14. EXTRN    VIOWRTTTY:FAR, VIOGETCURPOS:FAR, VIOSETCURPOS:FAR
  15. EXTRN    VIOGETCURTYPE:FAR, VIOSETCURTYPE:FAR, VIOWRTNCHAR:FAR
  16. EXTRN    VIOWRTCHARSTR:FAR
  17.  
  18. ;
  19. LBUFF    SEGMENT WORD PUBLIC 'KBUFFER'
  20.  
  21. KEYLEN        EQU    2048
  22. SYNLEN        EQU    2048
  23.  
  24. KEYBUFF        DB    KEYLEN DUP(0)    ; BUFFER FOR COMMAND RECALL
  25. KEYTAIL        DW    0        ; POINTER TO END OF BUFFER
  26. CURRPTR        DW    0        ; POINTER TO CURRENT COMMAND
  27. FUNCBUFF    DB    256 DUP(0)    ; BUFFER FOR FUNCTION KEY RECALL
  28. FUNCPTR        DW    0        ; POINTER TO CHAR IN FUNCBUFF
  29. FUNCMAX        DW    0        ; END OF FUNCBUFF
  30. WORKBUFF    DB    256 DUP(0)    ; WORK BUFFER
  31. WORKPTR        DW    0        ; POINTER TO WORKBUFF
  32. WORKTAIL    DW    0        ; POINTER TO END OF WORKBUFF
  33. WORKMAX        DW    0        ; MAX SIZE FOR WORKBUFF
  34. XMITBUFF    DB    256 DUP(0)    ; BUFFER FOR RETURN FROM CALL
  35. EDIT_FLAG    DW    0        ; ALLOW COMMAND EDITING
  36. CHANGE_FLAG    DW    0        ; FLAG FOR LINE CHANGE
  37. INIT_CUR_ROW    DW    0        ; INITIAL CURSOR ROW
  38. INIT_CUR_COL    DW    0        ; INITIAL CURSOR COLUMN
  39. CURR_CUR_ROW    DW    0        ; CURRENT CURSOR ROW
  40. CURR_CUR_COL    DW    0        ; CURRENT CURSOR COLUMN
  41. LAST_LENGTH    DW    0        ; LENGTH OF LAST DISPLAYED COMMAND
  42. THIS_LENGTH    DW    0        ; LENGTH OF THIS COMMAND
  43. INSERT_STATE    DW    0        ; STATE OF INSERT
  44. KEYDEVBUF    DB    20 DUP(?)    ; BUFFER FOR KEYBOARD REQUEST
  45. KEYDEVPRM    DW    1        ; PARAMETER FOR KEYBOARD CALL
  46. KEYNAME        DB    'KBD$',0    ; NAME OF KEYBOARD
  47. KEYACT        DW    ?        ; KEYBOARD ACTION
  48. KEYHAND        DW    0        ; KEYBOARD HANDLE
  49. BLANK        DB    ' '        ; BLANK (SPACE) CHARACTER
  50. O_CUR_SLINE    DW    0        ; OLD CURSOR START LINE
  51. O_CUR_ELINE    DW    0        ; OLD CURSOR END LINE
  52. O_CUR_WIDTH    DW    0        ; OLD CURSOR WIDTH
  53. O_CUR_ATTR    DW    0        ; OLD CURSOR ATTRIBUTE
  54. CUR_SLINE    DW    0        ; CURSOR START LINE
  55. CUR_ELINE    DW    0        ; CURSOR END LINE
  56. CUR_WIDTH    DW    0        ; CURSOR WIDTH
  57. CUR_ATTR    DW    0        ; CURSOR ATTRIBUTE
  58. KBD_STATE    EQU    $
  59. KBD_ST_SIZE    DW    0        ; SIZE OF KBD STATE
  60. KBD_ST_MASK    DW    0        ; KBD STATE MASK
  61. KBD_ST_TAC    DW    0        ; KBD TURNAROUND CHARACTER
  62. KBD_ST_INTFL    DW    0        ; KBD INT FL
  63. KBD_ST_SHIFT    DW    0        ; KBD SHIFT STATE
  64.  
  65. SPECTABL    DW    DO_F1        ; 0X3B
  66.         DW    DO_F2        ; 0X3C
  67.         DW    DO_F3        ; 0X3D
  68.         DW    KEYLOOP        ; 0X3E
  69.         DW    KEYLOOP        ; 0X3F
  70.         DW    KEYLOOP        ; 0X40
  71.         DW    KEYLOOP        ; 0X41
  72.         DW    KEYLOOP        ; 0X42
  73.         DW    KEYLOOP        ; 0X43
  74.         DW    KEYLOOP        ; 0X44
  75.         DW    KEYLOOP        ; 0X45
  76.         DW    KEYLOOP        ; 0X46
  77. SPECTABL1    DW    DO_HOME        ; 0X47
  78.         DW    DO_UP        ; 0X48
  79.         DW    KEYLOOP        ; 0X49
  80.         DW    KEYLOOP        ; 0X4A
  81.         DW    DO_LEFT        ; 0X4B
  82.         DW    KEYLOOP        ; 0X4C
  83.         DW    DO_RIGHT    ; 0X4D
  84.         DW    KEYLOOP        ; 0X4E
  85.         DW    DO_END        ; 0X4F
  86.         DW    DO_DOWN        ; 0X50
  87.         DW    KEYLOOP        ; 0X51
  88.         DW    DO_INS        ; 0X52
  89.         DW    DO_DEL        ; 0X53
  90.  
  91. LBUFF    ENDS
  92.  
  93. SBUFF    SEGMENT    WORD PUBLIC 'SYN'
  94. SYNBUFF        DB    SYNLEN DUP(0)    ; ALIAS BUFFER
  95. SYNHEAD        DW    0        ; BUFFER HEAD
  96. SYNTAIL        DW    0        ; BUFFER TAIL
  97. PRINT_LINE    DB    256 DUP(0)    ; BUFFER FOR PRINT LINE
  98. WRITTEN        DW    0
  99. SBUFF    ENDS
  100. ;
  101.  
  102.     ASSUME    CS:KEYREP, DS:LBUFF, ES:SBUFF
  103. KEYREP    SEGMENT BYTE PUBLIC 'CODE'
  104. ;
  105. START    PROC    FAR            ; INITIALIZATION ROUTINE FOR DLL
  106.     PUSH    DS
  107.     MOV    AX,SEG LBUFF
  108.     MOV    DS,AX            ; SET UP DATA SEGMENT
  109.     
  110.     PUSH    DS
  111.     PUSH    OFFSET KEYNAME        ; FAR PTR TO NAME
  112.     PUSH    DS
  113.     PUSH    OFFSET KEYHAND        ; FAR PTR TO HANDLE
  114.     PUSH    DS
  115.     PUSH    OFFSET KEYACT        ; FAR PTR TO ACTION
  116.     PUSH    0
  117.     PUSH    0            ; LONG SIZE
  118.     PUSH    0            ; NORMAL FILE
  119.     PUSH    1            ; OPEN FLAG
  120.     PUSH    1C0H            ; OPEN MODE
  121.     PUSH    0
  122.     PUSH    0
  123.     CALL    DOSOPEN        ; OPEN KEYBOARD
  124.     CMP    AX,0
  125.     JNE    BADOPEN
  126.     MOV    LAST_LENGTH,0
  127.     MOV    THIS_LENGTH,0
  128.     POP    DS
  129.     MOV    AX,1            ; SHOW SUCCESS
  130.     RET
  131. BADOPEN:
  132.     POP    DS
  133.     MOV    AX,0            ; SHOW FAILURE
  134.     RET
  135. START    ENDP
  136.  
  137. ;
  138. ; KEYSTRIN IS THE ACTUAL REPLACEMENT FUNCTION FOR THE KBDSTRINGIN
  139. ;    SUBFUNCTION.
  140. ;
  141.  
  142.     PUBLIC    KEYSTRIN
  143. KEYSTRIN    PROC    FAR
  144.     PUSH    BP
  145.     MOV    BP,SP
  146.                 ; ON ENTRY STACK LOOKS LIKE:
  147.                 ; [BP+0] - BP
  148.                 ; [BP+2] - OS2 FAR RETURN ADDR
  149.                 ; [BP+6] - CALLER'S DS
  150.                 ; [BP+8] - NEAR ENTRY POINT
  151.                 ; [BP+10] - FUNCTION NUMBER
  152.                 ; [BP+12] - FAR RETURN TO CALLER
  153.                 ; [BP+16] - KBDHANDLE
  154.                 ; [BP+18] - IOWAIT
  155.                 ; [BP+20] - LENGTH
  156.                 ; [BP+24] - POINTER TO CHAR BUFFER
  157.                 ;
  158.  
  159.     CMP    WORD PTR [BP+10],05
  160.     JE    OURFUNC            ; MAKE SURE THIS IS OUR FUNCTION
  161.     JMP    NOT_OURS
  162. ;
  163. OURFUNC:
  164.     PUSH    DI
  165.     PUSH    SI
  166.     PUSH    DS
  167.     PUSH    ES
  168.     PUSH    AX
  169.     PUSH    BX
  170.     PUSH    CX
  171.     PUSH    DX
  172.     PUSHF
  173.     MOV    AX,SEG LBUFF        ; SET UP DATA SEGMENT
  174.     MOV    DS,AX
  175.  
  176.     CMP    WORD PTR [BP+18],0    ; IS THIS A WAIT CALL
  177.     JE    CHK_STATE        ; YES, WE CAN HANDLE IT
  178.     JMP    NOT_OURS        ; NO, PASS IT BACK ON TO KBD SYSTEM
  179. ;
  180. CHK_STATE:
  181.     PUSH    DS
  182.     PUSH    OFFSET KBD_STATE    ; FAR PTR TO KBDSTATE
  183.     PUSH    0
  184.     CALL    KBDGETSTATUS    ; GET KBD STATE
  185.     MOV    AX,KBD_ST_MASK
  186.     AND    AX,100B            ; WE ONLY HANDLE COOKED MODE
  187.     CMP    AX,0
  188.     JE    DO_FUNC
  189.     JMP    NOT_OURS        ; LET SOMEONE ELSE DO THIS
  190. ;
  191. DO_FUNC:                ; FINALLY WE CAN START
  192.     MOV    CHANGE_FLAG,0        ; MARK UNCHANGED
  193.     PUSH    DS
  194.     PUSH    OFFSET O_CUR_SLINE    ; FAR PTR TO CURSOR TYPE
  195.     PUSH    0
  196.     CALL    VIOGETCURTYPE    ; GET CURSOR TYPE
  197. ;
  198.     MOV    AX,[BP+22]        ; SEGMENT OF INPUT BUFFER LENGTH
  199.     MOV    ES,AX
  200.     MOV    BX,[BP+20]        ; OFFSET OF INPUT BUFFER LENGTH
  201.     MOV    AX,ES:[BX]        ; INPUT BUFFER LENGTH
  202.     MOV    WORKMAX,AX
  203.     MOV    AX,ES:[BX+2]        ; EDITING FLAG
  204.     MOV    EDIT_FLAG,AX
  205. ;
  206. GET_CUR:
  207.     PUSH    DS
  208.     PUSH    OFFSET INIT_CUR_ROW    ; FAR PTR TO CURSOR ROW
  209.     PUSH    DS
  210.     PUSH    OFFSET INIT_CUR_COL    ; FAR PTR TO CURSOR COLUMN
  211.     PUSH    0
  212.     CALL    VIOGETCURPOS    ; GET INITIAL CURSOR POSITION
  213. ;
  214.     MOV    AX,INIT_CUR_ROW
  215.     MOV    CURR_CUR_ROW,AX
  216.     MOV    AX,INIT_CUR_COL
  217.     MOV    CURR_CUR_COL,AX
  218.     XOR    AX,AX
  219.     MOV    WORKPTR,AX
  220.     INC    AX
  221.     MOV    WORKTAIL,AX
  222.  
  223.     PUSH    DS
  224.     POP    ES            ; MAKE SEGMENTS THE SAME
  225.     CLD                ; SET DIRECTION JUST TO BE SAFE
  226. ;
  227. KEYLOOP:                ; MAJOR WAIT FOR KEY LOOP
  228.     CALL    GETKEY
  229.     CMP    AX,0
  230.     JE    FUNC_OK
  231.     JMP    BAD_FUNC
  232. ;
  233. FUNC_OK:
  234.     MOV    SI,OFFSET KEYDEVBUF
  235.     LODSW                ; SCAN_CODE AND CHAR_CODE
  236.     CMP    AL,0            ; SPECIAL KEY?
  237.     JNE    AT_KEY
  238.     JMP    SPEC_KEY
  239. ;
  240. AT_KEY:    CMP    AL,0E0H            ; 101 KEY SPECIAL KEY?
  241.     JNE    NORM_KEY        ; NO
  242.     JMP    SPEC_KEY
  243. ;
  244. NORM_KEY:
  245.     CMP    AL,0DH            ; THIS REALLY SHOULD BE TAC
  246.     JNE    IS_ESC
  247.     JMP    DO_CR
  248.  
  249. IS_ESC:    CMP    AL,1BH
  250.     JNE    IS_BS
  251.     JMP    DO_ESC
  252.  
  253. IS_BS:    MOV    CHANGE_FLAG,1        ; SHOW LINE HAS CHANGED
  254.     CMP    AL,08H
  255.     JNE    ASC_KEY
  256.     JMP    DO_BS
  257. ;
  258. ; AT ASK_KEY WE HAVE A NORMAL CHARACTER, CHECK INSERT MODE AND
  259. ;    DO KEY HANDLING
  260. ;
  261. ASC_KEY:
  262.     MOV    CX,WORKTAIL
  263.     CMP    CX,WORKMAX        ; DO WE HAVE MAX CHARACTERS?
  264.     JNE    ASC_KEY1        ; NO
  265.     JMP    TOO_MANY        ; YES
  266. ;
  267. ASC_KEY1:
  268.     CMP    INSERT_STATE,0
  269.     JE    OVERWRITE
  270.     JMP    INSERT
  271.  
  272. OVERWRITE:
  273.     MOV    DI,WORKPTR        ; CURR CHARACTER
  274.     ADD    DI,OFFSET WORKBUFF
  275.     STOSB                ; SAVE CHARACTER
  276.     SUB    DI,OFFSET WORKBUFF
  277.     MOV    AX,1            ; UPDATE CURSOR BY 1 POSITION
  278.     CALL    DISPTAIL        ; DISPLAY
  279.     MOV    WORKPTR,DI        ; SAVE WORKPTR
  280.     MOV    FUNCPTR,DI        ; SAVE FOR FUNCTION KEY RECALL
  281.     CMP    WORKTAIL,DI        ; ARE WE INSIDE LINE OR AT END?
  282.     JNE    O1            ; INSIDE LINE, DO NOT EXTEND BUFFER
  283.  
  284.     INC    WORKTAIL        ; INC LINE LENGTH
  285.     INC    THIS_LENGTH
  286.     MOV    AX,THIS_LENGTH
  287.     CMP    AX,LAST_LENGTH
  288.     JLE    O1
  289.     INC    LAST_LENGTH
  290. ;
  291. O1:    JMP    KEYLOOP            ; AND LOOP
  292. ;
  293. INSERT:
  294.     PUSH    AX            ; SAVE CHARACTER
  295.     MOV    DI,WORKTAIL        ; GET END OF BUFFER
  296.     DEC    DI            ; LESS ONE
  297.     MOV    SI,DI            ; TO SOURCE REGISTER
  298.     DEC    SI            ; LESS ONE
  299.     MOV    CX,DI
  300.     SUB    CX,WORKPTR        ; COUNT OF CHARACTERS TO MOVE
  301.     ADD    DI,OFFSET WORKBUFF
  302.     ADD    SI,OFFSET WORKBUFF
  303.     PUSHF                ; SAVE FLAGS (WE NEED TO CHANGE DIR)
  304.     STD
  305.     REP    MOVSB            ; MOVE CHARACTERS
  306.     POPF                ; RESTORE FLAGS (DIRECTION)
  307.     MOV    DI,WORKPTR        ; GET CHAR PTR
  308.     POP    AX            ; RESTORE CHARACTER
  309.     ADD    DI,OFFSET WORKBUFF
  310.     STOSB                ; STASH CHARACTER IN BUFFER
  311.     MOV    AX,1            ; UPDATE CURSOR BY 1 POSITION
  312.     CALL    DISPTAIL        ; DO DISPLAY
  313.     INC    WORKPTR
  314.     INC    WORKTAIL        ; EXTEND LINE LENGTH
  315.     JMP    KEYLOOP
  316. ;
  317. ; AT DO_ESC WE HAVE READ AN ESCAPE KEY, CLEAR THE INPUT LINE AND 
  318. ;    RESTORE CURSOR TO ORIGINAL POSITION.
  319. ;
  320. DO_ESC:
  321.     PUSH    DS
  322.     PUSH    OFFSET BLANK        ; FAR PTR TO BLANK CHARACTER
  323.     MOV    AX,WORKTAIL
  324.     DEC    AX
  325.     ADD    AX,OFFSET WORKBUFF
  326.     PUSH    AX            ; NUMBER OF CHARACTERS TO WRITE
  327.     MOV    AX,INIT_CUR_ROW
  328.     PUSH    AX
  329.     MOV    AX,INIT_CUR_COL
  330.     PUSH    AX
  331.     PUSH    0
  332.     CALL    VIOWRTNCHAR    ; WRITE N CHARACTERS
  333.     MOV    AX,INIT_CUR_ROW
  334.     MOV    CURR_CUR_ROW,AX        ; RESET CURSOR POSITION
  335.     PUSH    AX
  336.     MOV    AX,INIT_CUR_COL
  337.     MOV    CURR_CUR_COL,AX
  338.     PUSH    AX
  339.     PUSH    0
  340.     CALL    VIOSETCURPOS
  341.     XOR    AX,AX
  342.     MOV    WORKPTR,AX
  343.     MOV    FUNCPTR,AX
  344.     INC    AX
  345.     MOV    WORKTAIL,AX
  346.     PUSH    DS
  347.     PUSH    OFFSET O_CUR_SLINE    ; FAR PTR TO CURSOR TYPE
  348.     XOR    AX,AX
  349.     MOV    INSERT_STATE,AX        ; CLEAR INSERT MODE
  350.     PUSH    AX
  351.     CALL    VIOSETCURTYPE
  352.     MOV    THIS_LENGTH,0
  353.     MOV    CHANGE_FLAG,0
  354.     MOV    FUNCPTR,0
  355.     JMP    KEYLOOP
  356. ;
  357. ; AT DO_BS WE HANDLE A BACKSPACE CHARACTER
  358. ;
  359. DO_BS:
  360.     MOV    AX,WORKPTR
  361.     CMP    AX,0
  362.     JNE    BS1
  363.     JMP    KEYLOOP            ; AT START OF LINE
  364. ;
  365. BS1:
  366.     MOV    CX,WORKTAIL
  367.     DEC    CX
  368.     CMP    CX,AX            ; AT END OF LINE?
  369.     JE    BS2            ; YES, EASY CASE
  370.     JMP    BS3            ; NO, HARDER CASE
  371. ;
  372. BS2:
  373.     DEC    AX            ; BACKUP WORKPTR
  374.     MOV    WORKPTR,AX
  375.     MOV    FUNCPTR,AX
  376.     DEC    WORKTAIL
  377.     MOV    DI,AX
  378.     ADD    DI,OFFSET WORKBUFF
  379.     MOV    AL,' '
  380.     STOSB                ; BLANK CHARACTER
  381.     MOV    AX,CURR_CUR_COL
  382.     DEC    AX
  383.     CMP    AX,-1            ; DID WE WRAP A LINE?
  384.     JNE    BS2A            ; NO
  385.     DEC    CURR_CUR_ROW        ; YES
  386.     MOV    AX,79
  387. BS2A:
  388.     MOV    CURR_CUR_COL,AX
  389.     PUSH    CURR_CUR_ROW
  390.     PUSH    CURR_CUR_COL
  391.     PUSH    0
  392.     CALL    VIOSETCURPOS
  393.     MOV    AX,0            ; DO NOT UPDATE CURSOR POSITION
  394.     CALL    DISPTAIL
  395.     DEC    THIS_LENGTH
  396.     JMP    KEYLOOP
  397. ;
  398. BS3:
  399.     DEC    AX
  400.     MOV    WORKPTR,AX
  401.     MOV    FUNCPTR,AX
  402.     MOV    DI,AX            ; DEST = WORKPTR
  403.     INC    AX
  404.     MOV    SI,AX            ; SOURCE = WORKPTR + 1
  405.     ADD    DI,OFFSET WORKBUFF
  406.     ADD    SI,OFFSET WORKBUFF
  407.     MOV    CX,WORKTAIL
  408.     DEC    CX
  409.     SUB    CX,WORKPTR        ; NUMBER OF CHARACTERS TO MOVE
  410.     REP    MOVSB
  411.  
  412.     DEC    WORKTAIL
  413.     MOV    BX,WORKTAIL
  414.     DEC    BX
  415.     MOV    AL,' '
  416.     MOV    WORKBUFF[BX],AL
  417.     MOV    AX,CURR_CUR_COL
  418.     DEC    AX
  419.     CMP    AX,-1
  420.     JNE    BS3A
  421.     DEC    CURR_CUR_ROW
  422.     MOV    AX,79
  423. ;
  424. BS3A:
  425.     MOV    CURR_CUR_COL,AX
  426.     PUSH    CURR_CUR_ROW
  427.     PUSH    CURR_CUR_COL
  428.     PUSH    0
  429.     CALL    VIOSETCURPOS
  430.     MOV    AX,0            ; DON'T UPDATE CURSOR POSITION
  431.     CALL    DISPTAIL
  432.     JMP    KEYLOOP
  433. ;
  434. ; AT DO_CR WE HAVE READ A FULL LINE. CLEAR UP OUT DATA AND PASS THE
  435. ;    STRING BACK TO THE CALLING PROGRAM.  MAKE CURRPTR POINT TO THE
  436. ;    END OF THIS STRING (FOR RECALL).
  437. ;
  438. DO_CR:
  439.     CMP    CHANGE_FLAG,0
  440.     JNE    DO_CR1            ; LINE HAS CHANGED, SAVE FOR RECALL
  441.     JMP    SEND_BUFF
  442. ;
  443. DO_CR1:
  444.     MOV    AX,WORKTAIL
  445.     CMP    AX,4
  446.     JGE    IS_FIRST
  447.     JMP    SEND_BUFF1        ; DON'T SAVE LINES OF < 3 CHARS
  448. ;
  449. IS_FIRST:
  450.     MOV    DI,KEYTAIL
  451.     INC    DI
  452.     AND    DI,KEYLEN-1        ; DEST = END OF KEYBUFF
  453.     MOV    SI,OFFSET WORKBUFF
  454.     MOV    CX,WORKTAIL
  455.     DEC    CX            ; NUMBER OF CHARS TO STORE
  456. ;
  457. MOVE_LOOP:
  458.     PUSH    DI
  459.     ADD    DI,OFFSET KEYBUFF
  460.     MOVSB
  461.     POP    DI
  462.     INC    DI
  463.     AND    DI,KEYLEN-1        ; HANDLE BUFFER WRAP
  464.     LOOP    MOVE_LOOP
  465. ;
  466.     ADD    DI,OFFSET KEYBUFF
  467.     MOV    AL,0
  468.     STOSB                ; MAKE ASCIIZ
  469.     SUB    DI,OFFSET KEYBUFF
  470.     MOV    KEYTAIL,DI
  471.     MOV    CURRPTR,DI        ; FOR COMMAND RECALL
  472.     JMP    SEND_BUFF1
  473. ;
  474. SEND_BUFF:
  475.     MOV    SI,CURRPTR
  476.     ADD    SI,OFFSET KEYBUFF
  477. SEND_BUFF0:
  478.     LODSB
  479.     CMP    AL,0
  480.     JNE    SEND_BUFF0
  481.     SUB    SI,OFFSET KEYBUFF
  482.     MOV    CURRPTR,SI
  483. SEND_BUFF1:
  484.     MOV    AL,0DH
  485.     MOV    DI,WORKTAIL
  486.     DEC    DI
  487.     MOV    LAST_LENGTH,DI        ; LENGTH OF LAST LINE
  488.     ADD    DI,OFFSET WORKBUFF
  489.     STOSB                ; STORE CR
  490.     MOV    AX,WORKTAIL
  491.     ADD    AX,INIT_CUR_COL
  492.     CMP    AX,80
  493.     JL    SEND_BUFF2
  494.     SUB    AX,80
  495.     INC    CURR_CUR_ROW
  496. SEND_BUFF2:
  497.     MOV    CURR_CUR_COL,AX
  498.     PUSH    CURR_CUR_ROW
  499.     PUSH    CURR_CUR_COL
  500.     PUSH    0
  501.     CALL    VIOSETCURPOS
  502.     MOV    AX,DI
  503.     DEC    AX
  504.     SUB    DI,OFFSET WORKBUFF
  505.     PUSH    DS
  506.     PUSH    AX            ; FAR PTR TO CR
  507.     PUSH    1            ; NUMBER OF CHARACTERS TO WRITE
  508.     XOR    AX,AX
  509.     MOV    THIS_LENGTH,AX        ; NEW LINE LENGTH
  510.     PUSH    AX            ; REQUIRED ZERO
  511.     CALL    VIOWRTTTY    ; DISPLAY CR
  512.     PUSH    ES
  513.     CALL    ALIAS            ; CHECK FOR ALIAS SUBSTITUTION
  514.     MOV    SI,OFFSET WORKBUFF
  515.     CMP    AX,1
  516.     JE    SEND_BUFF3        ; NO SUBSTITUTION
  517.     MOV    SI,OFFSET XMITBUFF    ; SUBSTITUTION MADE USE XMITBUFF
  518. SEND_BUFF3:
  519.     MOV    AX,WORD PTR [BP+26]    ; SEGMENT OF RECEIVING BUFFER
  520.     MOV    ES,AX
  521.     MOV    DI,WORD PTR [BP+24]    ; OFFSET OF RECEIVING BUFFER
  522.     MOV    CX,0            ; CLEAR COUNT
  523. SEND_BUFF4:
  524.     LODSB                ; GET CHAR
  525.     CMP    AL,0DH            ; LAST CHAR?
  526.     JE    SEND_BUFF5
  527.     STOSB                ; SEND CHAR
  528.     INC    CX
  529.     JMP    SEND_BUFF4
  530. SEND_BUFF5:
  531.     STOSB                ; SEND CR
  532.     MOV    AX,[BP+22]        ; SEGMENT OF RETURNED BUFFER LENGTH
  533.     MOV    ES,AX
  534.     MOV    BX,[BP+20]        ; OFFSET OF RETURNED BUFFER LENGTH
  535.     MOV    ES:[BX+2],CX        ; LENGTH (LESS CR)
  536.     POP    ES
  537.     JMP    KEYDONE            ; DO CLEANUP
  538. ;
  539. ; AT SPEC_KEY WE HAVE READ A SPECIAL KEY
  540. ;
  541. SPEC_KEY:
  542.     MOV    AL,AH
  543.     XOR    AH,AH
  544.     CMP    AX,3BH
  545.     JGE    IN_TAB1
  546.     JMP    KEYLOOP            ; UNUSED KEY
  547. ;
  548. IN_TAB1:
  549.     CMP    AX,47H
  550.     JGE    IN_TAB2
  551.     JMP    DO_TAB1            ; KEY IN TABLE 1
  552. ;
  553. IN_TAB2:
  554.     CMP    AX,54H
  555.     JGE    IS_CLFT
  556.     JMP    DO_TAB2            ; KEY IN TABLE 2
  557. IS_CLFT:
  558.     CMP    AX,73H
  559.     JNE    IS_CRT
  560.     JMP    DO_CLFT
  561. IS_CRT:
  562.     CMP    AX,74H
  563.     JNE    IS_CPUP
  564.     JMP    DO_CRT
  565. IS_CPUP:
  566.     CMP    AX,84H
  567.     JNE    IS_CPDN
  568.     JMP    DO_CPUP
  569. IS_CPDN:
  570.     CMP    AX,76H
  571.     JNE    NOT_IMP
  572.     JMP    DO_CPDN
  573. ;
  574. NOT_IMP:
  575.     JMP    KEYLOOP            ; NOT AN ASSIGNED KEY
  576. ;
  577. DO_TAB1:
  578.     SUB    AX,3BH            ; MAKE OFFSET INTO TABLE
  579.     SHL    AX,1            ; FOR WORD POINTERS
  580.     MOV    BX,AX
  581.     MOV    AX,SPECTABL[BX]
  582.     JMP    AX            ; DISPATCH
  583. ;
  584. DO_TAB2:
  585.     SUB    AX,47H            ; OFFSET INTO TABLE
  586.     SHL    AX,1
  587.     MOV    BX,AX
  588.     MOV    AX,SPECTABL1[BX]
  589.     JMP    AX            ; DISPATCH
  590. ;
  591. ;
  592. ; DO_CLFT - MOVE ONE WORD LEFT
  593. ;
  594. DO_CLFT:                ; MOVE ONE WORD CHARACTER LEFT
  595.     MOV    DL,' '
  596.     MOV    DH,'\'
  597.     MOV    AX,WORKPTR
  598.     CMP    AX,0
  599.     JNE    CLEFT1
  600.     JMP    KEYLOOP            ; AT LEFT BORDER
  601. CLEFT1:    ADD    AX,OFFSET WORKBUFF
  602.     MOV    BX,AX
  603. ;
  604. CLEFT2:    DEC    BX            ; LOOP TO FIND NON-DELIMITER
  605.     CMP    BX,OFFSET WORKBUFF    ; AT BEGINNING OF LINE
  606.     JE    CLEFT6            ; YES
  607.     CMP    [BX],DL            ; IS THIS A SPACE
  608.     JE    CLEFT2            ; YES LOOP
  609.     CMP    [BX],DH            ; IS THIS A '\'
  610.     JE    CLEFT2
  611. ;
  612. CLEFT3:    DEC    BX            ; FOUND A NON-DELIMITER NOW FIND THE
  613.     CMP    BX,OFFSET WORKBUFF    ; NEXT DELIMITER
  614.     JE    CLEFT6            ; AT BEGINNING OF LINE
  615.     CMP    [BX],DL            ; SPACE
  616.     JE    CLEFT4
  617.     CMP    [BX],DH            ; '\'
  618.     JNE    CLEFT3
  619. ;
  620. CLEFT4:    INC    BX
  621.     SUB    BX,OFFSET WORKBUFF
  622.     MOV    CX,WORKPTR
  623.     SUB    CX,BX            ; HOW FAR WE HAVE MOVED
  624.     MOV    WORKPTR,BX
  625.     MOV    FUNCPTR,BX
  626.     MOV    AX,CURR_CUR_COL
  627.     SUB    AX,CX            ; PAST BEGINNING OF LINE
  628.     CMP    AX,0
  629.     JGE    CLEFT5
  630.     ADD    AX,80            ; TRICK COLUMN NUMBER
  631.     MOV    CURR_CUR_COL,AX
  632.     MOV    AX,CURR_CUR_ROW
  633.     DEC    AX            ; ADJUST ROW
  634.     MOV    CURR_CUR_ROW,AX
  635.     JMP    CLEFT7
  636. ;
  637. CLEFT5:    MOV    CURR_CUR_COL,AX
  638.     JMP    CLEFT7
  639. ;
  640. CLEFT6:    MOV    BX,0
  641.     MOV    WORKPTR,BX
  642.     MOV    FUNCPTR,BX
  643.     MOV    AX,INIT_CUR_COL
  644.     MOV    CURR_CUR_COL,AX
  645.     MOV    AX,INIT_CUR_ROW
  646.     MOV    CURR_CUR_ROW,AX
  647. ;
  648. CLEFT7:    PUSH    CURR_CUR_ROW
  649.     PUSH    CURR_CUR_COL
  650.     PUSH    0
  651.     CALL    VIOSETCURPOS
  652.     JMP    KEYLOOP
  653. ;
  654.  
  655. ;
  656. ; AT DO_CRT WE WANT TO LOOK RIGHT UNTIL WE FIND A SPACE THEN KEEP LOOKING
  657. ;    UNTIL WE FIND A NON-SPACE
  658. ;
  659. DO_CRT:    MOV    BX,WORKPTR
  660.     MOV    AX,WORKTAIL
  661.     MOV    DL,' '
  662.     MOV    DH,'\'
  663.     DEC    AX
  664.     CMP    AX,BX
  665.     JNE    CRT1
  666.     JMP    KEYLOOP            ; AT END OF LINE
  667. ;
  668. CRT1:    INC    BX            ; NEXT CHAR
  669.     CMP    AX,BX            ; AT END?
  670.     JNE    CRT2            ; NO
  671.     JMP    CRT5            ; YES
  672. ;
  673. CRT2:    CMP    WORKBUFF[BX],DL        ; IS THIS A DELIMITER
  674.     JE    CRT3
  675.     CMP    WORKBUFF[BX],DH        ;
  676.     JNE    CRT1            ; NO, KEEP LOOKING
  677. ;
  678. CRT3:    INC    BX            ; YES, PASS IT
  679.     CMP    AX,BX            ; AT END?
  680.     JNE    CRT4            ; NO
  681.     JMP    CRT5            ; YES
  682. ;
  683. CRT4:    CMP    WORKBUFF[BX],DL        ; IS THIS A SPACE
  684.     JE    CRT3            ; YES, KEEP ON TRUCKING
  685.     CMP    WORKBUFF[BX],DH
  686.     JE    CRT3
  687. ;
  688. CRT5:    MOV    CX,BX
  689.     MOV    BX,WORKPTR
  690.     MOV    WORKPTR,CX
  691.     MOV    FUNCPTR,CX
  692.     SUB    CX,BX            ; LENGTH MOVED
  693.     MOV    AX,CURR_CUR_COL
  694.     ADD    AX,CX
  695.     CMP    AX,80
  696.     JL    CRT6
  697.     SUB    AX,80
  698.     MOV    CURR_CUR_COL,AX
  699.     MOV    AX,CURR_CUR_ROW
  700.     INC    AX
  701.     MOV    CURR_CUR_ROW,AX
  702.     JMP    CRT9
  703. ;
  704. CRT6:    MOV    CURR_CUR_COL,AX
  705. ;
  706. CRT9:    PUSH    CURR_CUR_ROW
  707.     PUSH    CURR_CUR_COL
  708.     PUSH    0
  709.     CALL    VIOSETCURPOS
  710.     JMP    KEYLOOP
  711. ;
  712. ; AT DO_LEFT WE SIMPLY MOVE THE CURSOR ONE CHARACTER TO THE LEFT
  713. ;
  714. DO_LEFT:
  715.     MOV    AX,WORKPTR
  716.     CMP    AX,0
  717.     JNE    LEFT1
  718.     JMP    KEYLOOP            ; AT BEGINNING OF LINE
  719. ;
  720. LEFT1:    DEC    AX
  721.     MOV    WORKPTR,AX
  722.     MOV    FUNCPTR,CX
  723.     MOV    AX,CURR_CUR_COL
  724.     CMP    AX,0
  725.     JNE    LEFT2
  726.     MOV    AX,80
  727.     MOV    BX,CURR_CUR_ROW
  728.     DEC    BX
  729.     MOV    CURR_CUR_ROW,BX
  730. ;
  731. LEFT2:    DEC    AX
  732.     MOV    CURR_CUR_COL,AX
  733.     PUSH    CURR_CUR_ROW
  734.     PUSH    CURR_CUR_COL
  735.     PUSH    0
  736.     CALL    VIOSETCURPOS
  737.     JMP    KEYLOOP
  738. ;
  739. ; AT DO_RIGHT WE SIMPLY MOVE THE CURSOR ONE CHARACTER TO THE RIGHT
  740. ;
  741. DO_RIGHT:
  742.     MOV    AX,WORKPTR
  743.     INC    AX
  744.     CMP    AX,WORKTAIL
  745.     JNE    RIGHT1
  746.     JMP    KEYLOOP                ; AT END OF LINE
  747. ;
  748. RIGHT1:    MOV    WORKPTR,AX
  749.     MOV    FUNCPTR,AX
  750.     MOV    AX,CURR_CUR_COL
  751.     INC    AX
  752.     CMP    AX,80
  753.     JNE    RIGHT2
  754.     MOV    AX,0
  755.     MOV    BX,CURR_CUR_ROW
  756.     INC    BX
  757.     MOV    CURR_CUR_ROW,BX
  758. ;
  759. RIGHT2:    MOV    CURR_CUR_COL,AX
  760.     PUSH    CURR_CUR_ROW
  761.     PUSH    CURR_CUR_COL
  762.     PUSH    0
  763.     CALL    VIOSETCURPOS
  764.     JMP    KEYLOOP
  765. ;
  766. ; AT DO_HOME WE MOVE TO THE BEGINNING OF THE LINE
  767. ;
  768. DO_HOME:
  769.     XOR    AX,AX
  770.     MOV    WORKPTR,AX
  771.     MOV    FUNCPTR,AX
  772.     MOV    AX,INIT_CUR_COL
  773.     MOV    CURR_CUR_COL,AX
  774.     MOV    BX,INIT_CUR_ROW
  775.     MOV    CURR_CUR_ROW,BX
  776.     PUSH    BX
  777.     PUSH    AX
  778.     PUSH    0
  779.     CALL    VIOSETCURPOS
  780.     JMP    KEYLOOP
  781. ;
  782. ; AT DO_END WE MOVE THE THE END OF THE LINE
  783. ;
  784. DO_END:    MOV    AX,WORKTAIL
  785.     DEC    AX
  786.     CMP    AX,WORKPTR
  787.     JNE    END1
  788.     JMP    KEYLOOP                ; ALREADY AT END
  789. ;
  790. END1:
  791.     CMP    AX,0
  792.     JNE    END2
  793.     JMP    KEYLOOP                ; NO LINE
  794. ;
  795. END2:    MOV    WORKPTR,AX
  796.     MOV    FUNCPTR,AX
  797.     MOV    BX,INIT_CUR_COL
  798.     ADD    AX,BX
  799.     CMP    AX,80
  800.     JL    END3
  801.     SUB    AX,80
  802.     MOV    BX,INIT_CUR_ROW
  803.     INC    BX
  804.     MOV    CURR_CUR_ROW,BX
  805. ;
  806. END3:    MOV    CURR_CUR_COL,AX
  807.     PUSH    CURR_CUR_ROW
  808.     PUSH    CURR_CUR_COL
  809.     PUSH    0
  810.     CALL    VIOSETCURPOS
  811.     JMP    KEYLOOP
  812. ;
  813. ; AT DO_INS WE TOGGLE THE INSERT_STATE AND CHANGE CURSOR SHAPE
  814. ;
  815. DO_INS:    PUSH    DS
  816.     PUSH    OFFSET CUR_SLINE
  817.     PUSH    0
  818.     CALL    VIOGETCURTYPE
  819. ;    
  820.     MOV    AX,INSERT_STATE
  821.     CMP    AX,1
  822.     JE    INS1
  823.     MOV    AX,1                ; NOW INSERT
  824.     MOV    INSERT_STATE,AX
  825.     MOV    AX,CUR_SLINE
  826.     SUB    AX,2
  827.     MOV    CUR_SLINE,AX
  828.     JMP    INS2
  829. ;
  830. INS1:    MOV    AX,0                ; NOW OVERWRITE
  831.     MOV    INSERT_STATE,AX
  832.     MOV    BX,O_CUR_SLINE            ; GET ORIG. CUR
  833.     MOV    AX,O_CUR_ELINE
  834.     MOV    CUR_SLINE,BX
  835.     MOV    CUR_ELINE,AX
  836. ;
  837. INS2:    PUSH    DS
  838.     PUSH    OFFSET CUR_SLINE
  839.     PUSH    0
  840.     CALL    VIOSETCURTYPE
  841.     JMP    KEYLOOP
  842. ;
  843. ; AT DO_DEL WE WANT TO DELETE THE CHARACTER AT THE CURSOR
  844. ;
  845. DO_DEL:    MOV    AX,WORKPTR
  846.     INC    AX
  847.     CMP    AX,WORKTAIL
  848.     JNE    DEL1
  849.     JMP    KEYLOOP                ; AT END OF LINE
  850. ;
  851. DEL1:    MOV    DI,WORKPTR
  852.     MOV    SI,DI
  853.     INC    SI
  854.     ADD    DI,OFFSET WORKBUFF
  855.     ADD    SI,OFFSET WORKBUFF
  856.     MOV    CX,WORKTAIL        ; END OF BUFFER
  857.     DEC    CX            ; LESS 1
  858.     MOV    WORKTAIL,CX
  859.     SUB    CX,WORKPTR        ; LENGTH OF CHARACTERS TO MOVE
  860.     PUSH    CX            ; WE WILL NEED THIS IN A SEC
  861.     REP    MOVSB            ; MOVE LINE IN BUFFER
  862. ;
  863.     POP    CX            ; RESTORE LENGTH
  864.     MOV    BX,WORKTAIL        ; PAST END OF LINE
  865.     DEC    BX
  866.     MOV    AL,20H
  867.     MOV    WORKBUFF[BX],AL
  868.     MOV    AX,0
  869.     CALL    DISPTAIL
  870.     JMP    KEYLOOP
  871. ;
  872.     INC    CX            ; NEED TO SHOW SPACE AT END OF LINE
  873.     PUSH    DS            ; SEGMENT OF LINE TO REDISPLAY
  874.     MOV    AX,WORKPTR
  875.     ADD    AX,OFFSET WORKBUFF
  876.     PUSH    AX            ; OFFSET OF LINE
  877.     PUSH    CX
  878.     PUSH    0            ; VIO HANDLE
  879.     CALL    VIOWRTTTY
  880. ;
  881.     DEC    THIS_LENGTH
  882.     PUSH    CURR_CUR_ROW
  883.     PUSH    CURR_CUR_COL
  884.     PUSH    0
  885.     CALL    VIOSETCURPOS
  886.     JMP    KEYLOOP
  887. ;
  888. ; AT DO_F1 WE WANT TO DUPLICATE THE OS/2 F1 KEY WHICH DISPLAYS THE PREVIOUS
  889. ;    LINE ONE CHARACTER AT A TIME
  890. ;
  891. DO_F1:    MOV    BX,WORKPTR
  892.     CMP    BX,FUNCMAX
  893.     JGE    DO_F1A
  894.     MOV    AL,FUNCBUFF[BX]        ; LOAD NEXT KEY
  895.     CMP    AL,0            ; IS IT END OF THE LINE
  896.     JE    DO_F1A            ; YES, DO NOTHING ELSE
  897.     INC    BX            ; NO, UPDATE FUNCPTR
  898.     MOV    FUNCPTR,BX
  899.     JMP    ASC_KEY            ; AND PRETEND THE KEY CAME FROM USER
  900. ;
  901. DO_F1A:    JMP    KEYLOOP
  902.  
  903. ;
  904. ; AT DO_F2 WE WANT TO COPY CHARACTERS FROM FUNCBUFF UNTIL WE FIND
  905. ;    THE KEY WE ARE LOOKING FOR
  906. ;
  907. DO_F2:    CALL    GETKEY
  908.     CMP    AX,0
  909.     JE    DO_F2A
  910.     JMP    BAD_FUNC
  911. ;
  912. DO_F2A:    MOV    SI,OFFSET KEYDEVBUF
  913.     LODSW                ; KEY SCAN_CODE AND CHAR_CODE
  914.     CMP    AL,0
  915.     JNE    DO_F2B
  916.     JMP    KEYLOOP
  917. ;
  918. DO_F2B:    MOV    SI,FUNCPTR
  919.     ADD    SI,OFFSET FUNCBUFF
  920.     MOV    DI,WORKPTR
  921.     ADD    DI,OFFSET WORKBUFF
  922.     MOV    AH,AL                ; SAVE TARGET CHARACTER
  923.     MOV    CX,0
  924.     MOV    BX,SI
  925.     MOV    DX,FUNCMAX
  926.     ADD    DX,OFFSET FUNCBUFF
  927.     LODSB                    ; ALWAYS MATCH FIRST CHAR
  928.     CMP    AL,0
  929.     JE    DO_F2E                ; UNLESS IT ZERO
  930. ;
  931. DO_F2C:    CMP    SI,DX
  932.     JGE    DO_F2E
  933.     LODSB
  934.     INC    CX
  935.     CMP    AL,AH
  936.     JE    DO_F2D
  937.     CMP    AL,0
  938.     JE    DO_F2E                ; DO NOT MOVE IF NOT FOUND
  939.     JMP    DO_F2C
  940. ;
  941. DO_F2D:    MOV    SI,BX
  942.     MOV    AX,CX                ; CX CONTAINS COUNT TO MOVE
  943.     PUSH    AX
  944.     REP    MOVSB
  945.     MOV    AL,0
  946.     STOSB
  947.     DEC    DI
  948.     POP    AX
  949.     SUB    DI,OFFSET WORKBUFF
  950.     PUSH    DI
  951.     INC    DI
  952.     MOV    WORKTAIL,DI
  953.     SUB    SI,OFFSET FUNCBUFF
  954.     MOV    FUNCPTR,SI
  955.     CALL    DISPTAIL
  956.     POP    DI
  957.     MOV    WORKPTR,DI
  958. DO_F2E:    JMP    KEYLOOP
  959. ;
  960. ; AT DO_F3 WE COPY THE REMAINDER OF FUNCBUFF INTO WORKBUFF
  961. ;
  962. DO_F3:    MOV    SI,FUNCPTR
  963.     ADD    SI,OFFSET FUNCBUFF
  964.     MOV    DI,WORKPTR
  965.     ADD    DI,OFFSET WORKBUFF
  966.     MOV    BX,FUNCMAX
  967.     ADD    BX,OFFSET FUNCBUFF
  968.     MOV    AL,[SI]
  969.     CMP    AL,0
  970.     JNE    DO_F3B
  971.     JMP    KEYLOOP
  972. ;
  973. DO_F3B:    CMP    SI,BX
  974.     JGE    DO_F3D
  975.     LODSB
  976.     CMP    AL,0
  977.     JE    DO_F3C
  978.     STOSB
  979.     JMP    DO_F3B
  980. ;
  981. DO_F3C:    MOV    ES:[DI],AL
  982.     SUB    SI,OFFSET FUNCBUFF
  983.     DEC    SI
  984.     MOV    FUNCPTR,SI
  985.     SUB    DI,OFFSET WORKBUFF
  986.     PUSH    DI
  987.     MOV    AX,DI
  988.     SUB    AX,WORKPTR
  989.     INC    DI
  990.     MOV    WORKTAIL,DI
  991.     CALL    DISPTAIL
  992.     POP    DI
  993.     MOV    WORKPTR,DI
  994. DO_F3D:    JMP    KEYLOOP
  995.  
  996. ;
  997. ; AT DO_UP CURRPTR WILL EITHER POINT TO THE END (ZERO) OF THE LAST LINE
  998. ;    ENTERED (FOR A NEW LINE), OR TO THE FIRST CHARACTER OF THE LAST
  999. ;    LINE RECALLED. IN ORDER TO RECALL A LINE WE MUST BACK CURRPTR
  1000. ;    UP TO THE BEGINNING OF A LINE. WE DO THIS BY SCANNING BACKWARDS
  1001. ;    UNTIL WE FIND A NON-ZERO CHARACTER AND THEN
  1002. ;    CONTINUING UNTIL WE FIND THE NEXT ZERO CHARACTER.
  1003. ;    NOTE THAT DO_UP WILL LEAVE CURRPTR POINTING TO THE FIRST CHAR
  1004. ;    OF THE LINE WE JUST RECALLED.
  1005. ;    ALSO NOTE THAT AT DO_UP, WE DECREMENT CURRPTR BEFORE WE START
  1006. ;    WHEREAS IN DO_DOWN WE START SCANNING AT CURRPTR.
  1007. ;
  1008. DO_UP:    MOV    CHANGE_FLAG,0        ; CLEAR CHANGE FLAG
  1009.     MOV    BX,CURRPTR
  1010. ;
  1011. UP_LOOP1:
  1012.     DEC    BX
  1013.     CMP    BX,-1
  1014.     JNE    UP_LOOP2
  1015.     MOV    BX,KEYLEN-1
  1016. UP_LOOP2:
  1017.     MOV    AL,KEYBUFF[BX]
  1018.     CMP    AL,0
  1019.     JNE    UP_LOOP3
  1020.     CMP    BX,CURRPTR
  1021.     JNE    UP_LOOP1
  1022.     JMP    DO_ESC            ; WE WENT THROUGH BUFFER, NO LINES
  1023. ;
  1024. UP_LOOP3:                    ; NON-ZERO BYTE
  1025.     CMP    BX,-1
  1026.     JNE    UP_LOOP4
  1027.     MOV    BX,KEYLEN
  1028. UP_LOOP4:
  1029.     MOV    AL,KEYBUFF[BX]
  1030.     DEC    BX
  1031.     CMP    AL,0
  1032.     JNE    UP_LOOP3
  1033. ;
  1034. ; FOUND THE NEXT ASCII ZERO, THIS IS THE END OF A LINE. SAVE NEW CURRPTR
  1035. ;
  1036. UP_LOOP5:
  1037.     INC    BX                ; FIX LATE DECREMENT
  1038.     INC    BX                ; POINT PAST ASCII ZERO
  1039.     AND    BX,KEYLEN-1
  1040.     MOV    CURRPTR,BX            ; MAKE THIS CURRENT LINE
  1041. ;
  1042. ; NOW MOVE THIS STRING (UP TO WORKMAX CHARACTERS) INTO WORKBUFF
  1043. ;
  1044.     MOV    DI,OFFSET WORKBUFF
  1045.     MOV    CX,WORKMAX
  1046. ;
  1047. UP_LOOP6:
  1048.     AND    BX,KEYLEN-1
  1049.     MOV    AL,KEYBUFF[BX]
  1050.     CMP    AL,0
  1051.     JE    UP_LOOP7
  1052.     STOSB
  1053.     INC    BX
  1054.     LOOP    UP_LOOP6
  1055. ;
  1056. ; AT UP_LOOP7 WE EITHER FELL OUT OF THE LOOP WITH AN ASCII ZERO OR
  1057. ;    WORKMAX CHARACTERS
  1058. ;
  1059. UP_LOOP7:
  1060.  
  1061.     SUB    DI,OFFSET WORKBUFF
  1062.     MOV    WORKPTR,DI            ; SET UP POINTERS
  1063.     MOV    FUNCPTR,DI
  1064.     INC    DI
  1065.     MOV    WORKTAIL,DI            ; INTO WORKBUFF
  1066. ;
  1067. ; NOW JOIN COMMON CODE TO DISPLAY WORKBUFF
  1068. ;
  1069.     JMP    DISPBUFF
  1070. ;
  1071. ; AT DO_DOWN WE WANT TO RECALL THE NEXT LINE FROM OUR CIRCULAR BUFFER.
  1072. ;    CURRPTR WILL EITHER POINT TO THE ZERO BEFORE THE LINE WE WISH
  1073. ;    TO RECALL OR IT WILL POINT TO THE FIRST CHARACTER OF THE LINE
  1074. ;    BEFORE THE ONE WE WISH TO RECALL.  IN EITHER EVENT WE SCAN FOR
  1075. ;    A ZERO THEN FOR THE FIRST NON-ZERO.  THAT IS THE FIRST CHARACTER
  1076. ;    OF THE LINE WE ARE SEEKING.
  1077. ;    NOTE THAT AT DO_DOWN WE START SCANNING AT CURRPTR WHILE IN DO_UP
  1078. ;    WE DECREMENT CURRPTR BEFORE WE START SCANNING.
  1079. ;
  1080. ;
  1081. DO_DOWN:
  1082.     MOV    CHANGE_FLAG,0            ; CLEAR CHANGE FLAG
  1083.     MOV    BX,CURRPTR
  1084. ;
  1085. DOWN_LOOP1:        ; WE NEED TO SCAN AHEAD UNTIL WE FIND
  1086.     MOV    AL,KEYBUFF[BX]            ; A ZERO CHARACTER
  1087.     CMP    AL,0
  1088.     JE    DOWN_LOOP2            ; FOUND IT
  1089.     INC    BX                ; 
  1090.     AND    BX,KEYLEN-1            ; KEEP IN RANGE
  1091.     CMP    BX,CURRPTR
  1092.     JNE    DOWN_LOOP1
  1093.     JMP    KEYLOOP                ; NOTHING IN BUFFER
  1094. ;
  1095. DOWN_LOOP2:                    ; NOW LOOK FOR NON-ZERO
  1096.     MOV    AL,KEYBUFF[BX]        
  1097.     CMP    AL,0
  1098.     JNE    DOWN_LOOP2A
  1099.     INC    BX
  1100.     AND    BX,KEYLEN-1
  1101.     CMP    BX,CURRPTR
  1102.     JNE    DOWN_LOOP2
  1103.     JMP    KEYLOOP                ; NOTHING IN BUFFER
  1104. ;
  1105. DOWN_LOOP2A:
  1106.                     ; FIRST NON-ZERO CHAR
  1107.                     ; WE FOUND THE END OF THIS LINE
  1108.                     ; SAVE CURRPTR AND SCAN TO FIRST
  1109.                     ; REAL CHARACTER OF THIS LINE
  1110.     MOV    CURRPTR,BX        ; SAVE CURRPTR FOR RECALL
  1111.     MOV    DI,OFFSET WORKBUFF
  1112.     MOV    CX,WORKMAX
  1113. ;
  1114. DOWN_LOOP3:
  1115.     AND    BX,KEYLEN-1        ; KEEP POINTER IN RANGE
  1116.     MOV    AL,KEYBUFF[BX]
  1117.     CMP    AL,0
  1118.     JE    DOWN_LOOP4
  1119.     STOSB
  1120.     INC    BX
  1121.     LOOP    DOWN_LOOP3
  1122. ;
  1123. ; AT DOWN_LOOP4, WE EITHER RAN OUT OF WORKMAX CHARACTERS OR WE FOUND
  1124. ;    AN ASCII ZERO. 
  1125. ;
  1126. DOWN_LOOP4:
  1127.     SUB    DI,OFFSET WORKBUFF
  1128.     MOV    WORKPTR,DI
  1129.     MOV    FUNCPTR,DI
  1130.     INC    DI
  1131.     MOV    WORKTAIL,DI
  1132. ;
  1133. ; AT DISPBUFF WE NEED TO DISPLAY THE CHARACTER STRING WE JUST MOVED INTO
  1134. ;    WORKBUFF.
  1135. ;
  1136. DISPBUFF:
  1137.     PUSH    INIT_CUR_ROW
  1138.     PUSH    INIT_CUR_COL
  1139.     PUSH    0                ; RESET 
  1140.     CALL    VIOSETCURPOS
  1141.     PUSH    DS
  1142.     PUSH    OFFSET BLANK
  1143.     PUSH    LAST_LENGTH            ; LENGTH OF LAST LINE
  1144.     PUSH    INIT_CUR_ROW
  1145.     PUSH    INIT_CUR_COL
  1146.     PUSH    0
  1147.     CALL    VIOWRTNCHAR
  1148.     PUSH    DS
  1149.     PUSH    OFFSET WORKBUFF
  1150.     PUSH    WORKPTR
  1151.     PUSH    0
  1152.     CALL    VIOWRTTTY
  1153.     PUSH    DS
  1154.     PUSH    OFFSET CURR_CUR_ROW
  1155.     PUSH    DS
  1156.     PUSH    OFFSET CURR_CUR_COL
  1157.     PUSH    0
  1158.     CALL    VIOGETCURPOS
  1159.     MOV    AX,WORKPTR
  1160.     MOV    LAST_LENGTH,AX
  1161.     ADD    AX,INIT_CUR_COL
  1162.     CMP    AX,80
  1163.     JL    DISPBUFF1
  1164.     MOV    AX,INIT_CUR_ROW
  1165.     CMP    AX,CURR_CUR_ROW
  1166.     JNE    DISPBUFF1
  1167.     DEC    INIT_CUR_ROW
  1168. DISPBUFF1:
  1169.     JMP    KEYLOOP
  1170. ;
  1171. ; AT DO_CPUP WE WANT TO CLEAR THE ENTIRE RECALL BUFFER
  1172. ;
  1173. DO_CPUP:
  1174.     MOV    DI,OFFSET KEYBUFF
  1175.     MOV    CX,KEYLEN
  1176.     MOV    AL,0
  1177.     REP    STOSB
  1178.     MOV    KEYTAIL,0
  1179.     MOV    CURRPTR,0
  1180.     JMP    DO_ESC            ; CLEAR LINE
  1181. ;
  1182. ; AT DO_CPDN WE NEED TO DELETE THE CURRENT LINE (POINTED TO BY CURRPTR).
  1183. ;    NOTE THAT CURRPTR WILL POINT TO THE FIRST CHAR OF THE CURRENTLY
  1184. ;    RECALLED LINE.  IF IT POINTS TO A ZERO, WE HAVE NOT DONE A RECALL
  1185. ;    SO SHOULD NOT ALLOW THE DELETION
  1186. ;
  1187. DO_CPDN:
  1188.     MOV    BX,CURRPTR        ; POINT TO CURRENT LINE
  1189. ;
  1190. DO_CPDN1:
  1191.     MOV    AL,KEYBUFF[BX]
  1192.     CMP    AL,0            ; IF ZERO WE ARE DONE
  1193.     JE    DO_CPDN2
  1194.     MOV    AL,0            ; CLEAR THIS CHAR
  1195.     MOV    KEYBUFF[BX],AL
  1196.     INC    BX            ; POINT TO NEXT
  1197.     AND    BX,KEYLEN-1        ; KEEP IN RANGE
  1198.     CMP    BX,CURRPTR        ; HAVE WE LOOPED
  1199.     JE    DO_CPDN2        ; YES
  1200.     JMP    DO_CPDN1        ; NO, KEEP CLEARING
  1201. ;
  1202. DO_CPDN2:
  1203.     JMP    DO_UP
  1204. ;
  1205. ; AT TOO_MANY WE ALREADY HAVE AS MANY KEYS AS WE WILL ACCEPT
  1206. ;
  1207. TOO_MANY:
  1208.     PUSH    300
  1209.     PUSH    16
  1210.     CALL    DOSBEEP
  1211.     PUSH    600
  1212.     PUSH    16
  1213.     CALL    DOSBEEP
  1214.     JMP    KEYLOOP
  1215. ;
  1216. ; AT KEYDONE WE HAVE FINISHED ALL EDITING FUNCTIONS. MOVE THE NEW LINE
  1217. ;    INTO THE FUNCTION KEY BUFFER. CLEAN UP THE STACK AND GO HOME.
  1218. ;
  1219. KEYDONE:
  1220.     MOV    DI,OFFSET FUNCBUFF
  1221.     MOV    SI,OFFSET WORKBUFF
  1222.     MOV    CX,WORKTAIL
  1223.     MOV    FUNCMAX,CX
  1224.     DEC    CX
  1225.     REP    MOVSB
  1226.     MOV    AL,0
  1227.     STOSB
  1228.     MOV    FUNCPTR,0
  1229. ;    
  1230.     PUSH    DS
  1231.     PUSH    OFFSET O_CUR_SLINE
  1232.     PUSH    0
  1233.     CALL    VIOSETCURTYPE
  1234.     POPF
  1235.     POP    DX
  1236.     POP    CX
  1237.     POP    BX
  1238.     POP    AX
  1239.     POP    ES
  1240.     POP    DS
  1241.     POP    SI
  1242.     POP    DI
  1243.     POP    BP
  1244.     MOV    AX,0
  1245.     RET
  1246.  
  1247. NOT_OURS:
  1248.     POPF
  1249.     POP    DX
  1250.     POP    CX
  1251.     POP    BX
  1252.     POP    AX
  1253.     POP    ES
  1254.     POP    DS
  1255.     POP    SI
  1256.     POP    DI
  1257.     POP    BP
  1258. NOT_OURS1:
  1259.     MOV    AX,-1
  1260.     RET
  1261.  
  1262. BAD_FUNC:
  1263.     PUSH    DS
  1264.     PUSH    OFFSET O_CUR_SLINE
  1265.     PUSH    0
  1266.     CALL    VIOSETCURTYPE
  1267.     POPF
  1268.     POP    DX
  1269.     POP    CX
  1270.     POP    BX
  1271.     POP    AX
  1272.     POP    ES
  1273.     POP    DS
  1274.     POP    SI
  1275.     POP    DI
  1276.     POP    BP
  1277.     MOV    AX,-1
  1278.     RET
  1279.  
  1280. KEYSTRIN ENDP
  1281.  
  1282. ;
  1283. ; GETKEY IS THE CALL TO READ ANOTHER KEY FROM DEVICE DRIVER
  1284. ;
  1285. GETKEY    PROC    NEAR
  1286.     PUSH    DS
  1287.     PUSH    OFFSET KEYDEVBUF
  1288.     PUSH    DS
  1289.     PUSH    OFFSET KEYDEVPRM
  1290.     PUSH    74H            ; READ CHARACTER FUNCTION
  1291.     PUSH    04H            ; KEYBOARD CONTROL CATEGORY
  1292.     MOV    AX,KEYHAND
  1293.     PUSH    AX
  1294.     CALL    DOSDEVIOCTL
  1295.     RET
  1296. GETKEY    ENDP
  1297.  
  1298. ;
  1299. ; DISPTAIL WILL (RE)DISPLAY WORKBUFF FROM WORKPTR TO WORKTAIL
  1300. ;    IF AX == 0 THE CURRENT CURSOR POSITION WILL NOT BE UPDATED UNLESS
  1301. ;    A LINE WRAP OCCURRED, THEN CURR_CUR_ROW AND INIT_CUR_ROW WILL BE
  1302. ;    FIXED. IF AX != 0 CURSOR WILL BE BUMPED BY AX POSITIONS.
  1303. ;    THIS_LENGTH WILL ALWAYS BE UPDATED
  1304. ;
  1305. DISPTAIL PROC    NEAR
  1306.     PUSH    BX
  1307.     PUSH    CX
  1308.     PUSH    DX
  1309.     PUSH    AX
  1310.     MOV    AX,WORKTAIL
  1311.     DEC    AX
  1312.     MOV    THIS_LENGTH,AX
  1313.     CMP    AX,LAST_LENGTH
  1314.     JLE    DISPT1
  1315.     MOV    LAST_LENGTH,AX
  1316. DISPT1:
  1317.     PUSH    DS
  1318.     MOV    AX,WORKPTR
  1319.     ADD    AX,OFFSET WORKBUFF
  1320.     PUSH    AX
  1321.     MOV    AX,WORKTAIL
  1322.     SUB    AX,WORKPTR
  1323.     PUSH    AX
  1324.     XOR    AX,AX
  1325.     PUSH    AX
  1326.     CALL    VIOWRTTTY
  1327.     MOV    BX,CURR_CUR_ROW        ; SAVE OLD CUR_POS
  1328.     MOV    CX,CURR_CUR_COL
  1329.     PUSH    DS
  1330.     PUSH    OFFSET CURR_CUR_ROW
  1331.     PUSH    DS
  1332.     PUSH    OFFSET CURR_CUR_COL
  1333.     PUSH    0
  1334.     CALL    VIOGETCURPOS
  1335.     POP    AX            ; SHOULD WE UPDATE CUR_POS
  1336.     CMP    AX,0            ; TO END OF LINE
  1337.     JE    NO_UPDATE_CUR        ; NO
  1338.     JMP    UPDATE_CUR
  1339. ;
  1340. NO_UPDATE_CUR:
  1341.     MOV    AX,WORKTAIL        ; NO UPDATE
  1342.     ADD    AX,INIT_CUR_COL
  1343.     CMP    AX,80            ; DID WE WRAP A LINE?
  1344.     JL    RESET_CUR        ; NO
  1345.     MOV    AX,INIT_CUR_ROW        ; YES
  1346.     CMP    AX,CURR_CUR_ROW        ; DID ROW CHANGE
  1347.     JNE    RESET_CUR        ; NO, THE SCREEN DID NOT SCROLL
  1348.     DEC    AX            ; YES, THE SCREEN SCROLLED
  1349.     MOV    INIT_CUR_ROW,AX        ; MOVE INIT_CUR_ROW BACK ONE
  1350.     MOV    BX,AX            ; SHOW CURR_CUR_ROW BACK ONE
  1351. RESET_CUR:
  1352.     MOV    CURR_CUR_ROW,BX        ; DO NOT UPDATE CURSOR POSITION
  1353.     MOV    CURR_CUR_COL,CX
  1354.     PUSH    BX            ; RESET CURSOR POSITION
  1355.     PUSH    CX
  1356.     PUSH    0
  1357.     CALL    VIOSETCURPOS
  1358.     JMP    DISPTDONE
  1359. ;
  1360. ;
  1361. UPDATE_CUR:
  1362.     MOV    CURR_CUR_ROW,BX
  1363.     MOV    CURR_CUR_COL,CX
  1364.     ADD    AX,CX
  1365.     MOV    CURR_CUR_COL,AX
  1366.     CMP    AX,80
  1367.     JL    DISPTDONE        ; NO LINE WRAP
  1368.     SUB    AX,80
  1369.     MOV    CURR_CUR_COL,AX
  1370.     INC    CURR_CUR_ROW
  1371.     MOV    AX,INIT_CUR_ROW
  1372.     CMP    AX,CURR_CUR_ROW        ; THERE WAS A LINE WRAP
  1373.     JNE    DISPTDONE        ; BUT THE SCREEN DID NOT SCROLL
  1374.     DEC    AX            ; THE SCREEN DID SCROLL
  1375.     MOV    INIT_CUR_ROW,AX        ; SHOW INIT_CUR AS BACK ONE LINE
  1376. ;
  1377. DISPTDONE:
  1378.     PUSH    CURR_CUR_ROW
  1379.     PUSH    CURR_CUR_COL
  1380.     PUSH    0
  1381.     CALL    VIOSETCURPOS
  1382.     POP    DX
  1383.     POP    CX
  1384.     POP    BX
  1385.     RET
  1386.  
  1387. DISPTAIL ENDP
  1388.  
  1389. ;
  1390. ; ADDSYN IS THE PUBLIC ENTRY POINT TO THE ALIAS SYSTEM.
  1391. ;    ADDSYN IS CALLED WITH A FAR POINTER TO AN ASCIIZ ALIAS.
  1392. ;    THE ALIAS TAKES THE FORM OF ALIAS REPLACEMENT. ALIAS MUST NOT
  1393. ;    CONTAIN ANY SPACES, REPLACEMENT IS ASCIIZ.  ON RETURN AX == 0
  1394. ;    IF SUCCESSUFLLY ADDED, AX != 0 IF BUFFER FULL.
  1395. ;
  1396. ; THE ALIAS BUFFER CONSISTS OF SETS OF ALIAS REPLACEMENTS STORED AS FOLLOWS:
  1397. ;    ALIASA,0FFH,REPLACEMENTA,0H,ALIASB,0FFH,REPLACEMENTB,0H...
  1398. ;    ALIASN,0FFH,REPLACEMENTN,0H,0FFH
  1399. ;
  1400.     ASSUME    CS:KEYREP, DS:SBUFF, ES:LBUFF
  1401.     PUBLIC    ADDSYN
  1402. ;
  1403. ADDSYN    PROC    FAR
  1404.     PUSH    BP
  1405.     MOV    BP,SP
  1406.     PUSH    BX
  1407.     PUSH    CX
  1408.     PUSH    DX
  1409.     PUSH    DI
  1410.     PUSH    SI
  1411.     PUSH    ES
  1412.     PUSH    DS
  1413.     MOV    AX,SEG SBUFF
  1414.     MOV    DS,AX
  1415.  
  1416.     ASSUME    ES:SBUFF
  1417. ;
  1418. A0:
  1419.                     ; OK, WE ARE LOADED.
  1420.                     ; STACK LOOKS LIKE THIS:
  1421.                     ; [BP+0] - BP
  1422.                     ; [BP+2] - RETURN SEGMENT
  1423.                     ; [BP+4] - RETURN OFFSET
  1424.                     ; [BP+6] - OFFSET OF ALIAS STRING
  1425.                     ; [BP+8] - SEGMENT OF ALIAS STRING
  1426.     MOV    AX,SEG SBUFF
  1427.     MOV    ES,AX
  1428.     MOV    DI,ES:SYNHEAD        ; ES:DI POINTS TO ALIAS BUFFER
  1429.     MOV    AX,[BP+8]
  1430.     MOV    DS,AX
  1431.     MOV    SI,[BP+6]        ; DS:SI POINTS TO ALIAS STRING
  1432.     MOV    DX,SYNLEN-1
  1433.     MOV    CX,0
  1434.     PUSH    SI
  1435. ;
  1436. A1:                    ; SCAN FOR LENGTH OF ALIAS
  1437.     LODSB
  1438.     INC    CX
  1439.     CMP    AL,' '
  1440.     JE    A2
  1441.     CMP    AL,0
  1442.     JNE    A1
  1443.     JMP    DEL_SYN
  1444. ;
  1445. A2:
  1446.     DEC    CX
  1447.     POP    SI
  1448.     CMP    DI,ES:SYNTAIL        ; ARE WE AT START OF BUFFER?
  1449.     JE    ADDSYN1            ; YES, JUST DO ADD
  1450.     CALL    CMPSTR            ; NO, LOOK FOR ALIAS
  1451.     CMP    AX,0
  1452.     JNE    ADDSYN1
  1453.     JMP    REPLACE_SYN
  1454. ;
  1455. ADDSYN1:
  1456.     MOV    CX,0            ; CLEAR COUNT
  1457.     PUSH    SI            ; POINTER TO ALIAS STRING
  1458. ;
  1459. ALIAS_LEN:
  1460.     LODSB                ; GET CHAR
  1461.     INC    CX
  1462.     CMP    AL,0
  1463.     JNE    ALIAS_LEN
  1464. ;
  1465.     PUSH    CX            ; CONTAINS LENGTH OF NEW ALIAS
  1466.     PUSH    DI            ; END OF ALIAS BUFFER
  1467. ALIAS_LEN1:
  1468.     INC    DI
  1469.     CMP    DI,SYNLEN
  1470.     JE    NO_ROOM
  1471.     LOOP    ALIAS_LEN1
  1472.     JMP    HAVE_ROOM
  1473. ;
  1474. NO_ROOM:                ; NOT ENOUGH ROOM FOR NEW ALIAS
  1475.     POP    DI
  1476.     POP    CX
  1477.     POP    SI
  1478.     JMP    ADD_FAIL
  1479. ;
  1480. HAVE_ROOM:                ; WE HAVE ROOM
  1481.     POP    DI
  1482.     POP    CX
  1483.     POP    SI
  1484.     PUSH    DI            ; SAVE POINTER FOR A MOMENT
  1485. ;
  1486. PUT_ALIAS_IN:
  1487.     LODSB
  1488.     STOSB
  1489.     LOOP    PUT_ALIAS_IN
  1490.     MOV    AL,0FFH            ; MARK END OF ALIAS
  1491.     STOSB                ; STORE IT
  1492.     MOV    ES:SYNTAIL,DI        ; NEW SYNTAIL
  1493.     POP    DI            ; RESTORE POINTER TO START
  1494. ;
  1495. FIND_FIRST_SPACE:
  1496.     MOV    AL,ES:[DI]
  1497.     CMP    AL,' '            ; SCAN FOR FIRST SPACE
  1498.     JE    FOUND_FIRST_SPACE
  1499.     INC    DI
  1500.     JMP    FIND_FIRST_SPACE
  1501. ;
  1502. FOUND_FIRST_SPACE:
  1503.     MOV    AL,0FFH
  1504.     MOV    ES:[DI],AL
  1505.     POP    DS
  1506.     POP    ES
  1507.     POP    SI
  1508.     POP    DI
  1509.     POP    DX
  1510.     POP    CX
  1511.     POP    BX
  1512.     POP    BP
  1513.     MOV    AX,0
  1514.     RET    4
  1515. ;
  1516. ; AT REPLACE_SYN, WE NEED TO REPLACE AN EXISTING ALIAS.  WHAT WE WILL DO
  1517. ;    IS TO DELETE THIS ALIAS AND SLIDE THE BUFFER CLOSED.  WE THEN
  1518. ;    REJOIN THE CODE TO ADD AN ALIAS.  ON ENTRY DI POINTS TO THE
  1519. ;    START OF THE REPLACEMENT STRING FOR THIS ALIAS SOURCE.  WE NEED
  1520. ;    TO BACK DI UP TO THE START OF THIS ALIAS.
  1521. ;
  1522. REPLACE_SYN:
  1523.     PUSH    DS
  1524.     PUSH    ES
  1525.     POP    DS
  1526. R1:
  1527.     DEC    DI
  1528.     CMP    DI,0            ; AT START OF BUFFER?
  1529.     JE    R1A
  1530.     CMP    BYTE PTR [DI],0        ; AT START OF ALIAS
  1531.     JNE    R1            ; NO, KEEP LOOKING
  1532.     INC    DI            ; POINT DI TO FIRST CHAR OF ALIAS
  1533. R1A:
  1534.     MOV    SI,DI
  1535. ;
  1536. R2:                    ; SCAN FOR END OF REPLACEMENT
  1537.     LODSB
  1538.     CMP    AL,0
  1539.     JNE    R2
  1540. ;
  1541.     CMP    BYTE PTR [SI],0FFH    ; WAS THIS LAST STRING?
  1542.     JNE    R3            ; NO
  1543.     MOV    AL,0FFH            ; YES, JUST MARK END.
  1544.     STOSB                ; DI STILL POINTS TO START.
  1545.     MOV    SYNTAIL,DI
  1546.     JMP    LAST_ALIAS
  1547. ;
  1548. R3:
  1549.     MOV    CX,SYNTAIL
  1550.     SUB    CX,SI            ; COUNT OF CHARACTERS TO MOVE
  1551.     REP    MOVSB
  1552.     MOV    SYNTAIL,DI
  1553. ;
  1554. LAST_ALIAS:
  1555.     POP    DS
  1556.     JMP    A0            ; JOIN CODE FOR ADD.
  1557. ;
  1558. ; AT DEL_SYN WE NEED TO REMOVE THIS ALIAS ENTIRELY
  1559. ;    THE LOGIC IS THE SAME AS REPLACE_SYN ABOVE.
  1560. ;
  1561.  
  1562. DEL_SYN:
  1563.     DEC    CX            ; CX IS LENGTH OF ALIAS
  1564.     POP    SI            ; RESTORE START OF ALIAS
  1565.     CALL    CMPSTR            ; LOOK FOR ALIAS
  1566.     CMP    AX,0
  1567.     JNE    DEL_SYN5        ; ALIAS DOES NOT EXIST
  1568.     PUSH    ES
  1569.     POP    DS
  1570. DEL_SYN1:
  1571.     DEC    DI
  1572.     CMP    DI,0            ; AT START OF BUFFER?
  1573.     JE    DEL_SYN2
  1574.     CMP    BYTE PTR [DI],0        ; AT START OF ALIAS
  1575.     JNE    DEL_SYN1        ; NO, KEEP LOOKING
  1576.     INC    DI            ; POINT DI TO FIRST CHAR OF ALIAS
  1577. DEL_SYN2:
  1578.     MOV    SI,DI
  1579. ;
  1580. DEL_SYN3:                    ; SCAN FOR END OF REPLACEMENT
  1581.     LODSB
  1582.     CMP    AL,0
  1583.     JNE    DEL_SYN3
  1584. ;
  1585.     CMP    BYTE PTR [SI],0FFH    ; WAS THIS LAST STRING?
  1586.     JNE    DEL_SYN4        ; NO
  1587.     MOV    AL,0FFH            ; YES, JUST MARK END.
  1588.     STOSB                ; DI STILL POINTS TO START.
  1589.     MOV    SYNTAIL,DI
  1590.     JMP    DEL_SYN5
  1591. ;
  1592. DEL_SYN4:
  1593.     MOV    CX,SYNTAIL
  1594.     SUB    CX,SI            ; COUNT OF CHARACTERS TO MOVE
  1595.     REP    MOVSB
  1596.     MOV    SYNTAIL,DI
  1597. ;
  1598. DEL_SYN5:
  1599.     POP    DS
  1600.     POP    ES
  1601.     POP    SI
  1602.     POP    DI
  1603.     POP    DX
  1604.     POP    CX
  1605.     POP    BX
  1606.     POP    BP
  1607.     MOV    AX,0
  1608.     RET    4
  1609. ;
  1610. ADD_FAIL:
  1611.     POP    DS
  1612.     POP    ES
  1613.     POP    SI
  1614.     POP    DI
  1615.     POP    DX
  1616.     POP    CX
  1617.     POP    BX
  1618.     POP    BP
  1619.     MOV    AX,1
  1620.     RET    4
  1621. ;
  1622. ADD_FAIL2:
  1623.     POP    DS
  1624.     POP    ES
  1625.     POP    SI
  1626.     POP    DI
  1627.     POP    DX
  1628.     POP    CX
  1629.     POP    BX
  1630.     POP    BP
  1631.     MOV    AX,2
  1632.     RET    4
  1633. ;
  1634. ADDSYN    ENDP
  1635.  
  1636.     ASSUME    CS:KEYREP, DS:SBUFF, ES:SBUFF
  1637. ;
  1638. ; CLEARSYN WILL SIMPLY CLEAR OUT ALL ALIASES
  1639. ;
  1640.     PUBLIC    CLEARSYN
  1641.  
  1642. CLEARSYN PROC    FAR
  1643.     PUSH    BX
  1644.     PUSH    CX
  1645.     PUSH    DX
  1646.     PUSH    DS
  1647.     PUSH    ES
  1648. ;
  1649.     ASSUME    DS:SBUFF
  1650. ;
  1651. C1:
  1652.     MOV    AX,SEG SBUFF
  1653.     MOV    DS,AX
  1654.     XOR    AX,AX
  1655.     MOV    SYNHEAD,AX
  1656.     MOV    SYNTAIL,AX
  1657.     MOV    BX,AX
  1658.     MOV    CX,SYNLEN
  1659. CLEAR1:    MOV    [BX],AL
  1660.     INC    BX
  1661.     LOOP    CLEAR1
  1662. ;
  1663. CLEAR2:
  1664.     POP    ES
  1665.     POP    DS
  1666.     POP    DX
  1667.     POP    CX
  1668.     POP    BX
  1669.     MOV    AX,0
  1670.     RET
  1671. ;
  1672. CLEAR3:
  1673.     POP    ES
  1674.     POP    DS
  1675.     POP    DX
  1676.     POP    CX
  1677.     POP    BX
  1678.     MOV    AX,1
  1679.     RET
  1680.  
  1681. CLEARSYN ENDP
  1682.  
  1683.     ASSUME    CS:KEYREP, DS:SBUFF, ES:SBUFF
  1684.     PUBLIC    LIST_SYN
  1685. ;
  1686. ; LIST_SYN WILL LIST THE CURRENT ALIASES OUT TO STDOUT
  1687. ;
  1688. LIST_SYN PROC    FAR
  1689.     PUSH    BP
  1690.     MOV    BP,SP
  1691.     PUSH    BX
  1692.     PUSH    CX
  1693.     PUSH    DX
  1694.     PUSH    SI
  1695.     PUSH    DI
  1696.     PUSH    ES
  1697.     PUSH    DS
  1698.     MOV    AX,SEG SBUFF
  1699.     MOV    DS,AX
  1700.     JMP    LIST_SYN1
  1701. ;
  1702.     ASSUME    ES:SBUFF
  1703. ;
  1704. LIST_SYN1:
  1705.     MOV    AX,DS
  1706.     MOV    ES,AX
  1707.     MOV    SI,SYNHEAD
  1708.     CMP    SI,SYNTAIL
  1709.     JNE    GET_SYN0
  1710.     JMP    NO_SYN_LIST
  1711. ;
  1712. GET_SYN0:
  1713.     MOV    DI,OFFSET PRINT_LINE
  1714.     MOV    CX,0
  1715. GET_SYN:
  1716.     LODSB
  1717.     CMP    AL,0FFH
  1718.     JE    GET_SYN1
  1719.     STOSB
  1720.     INC    CX
  1721.     JMP    GET_SYN
  1722. ;
  1723. GET_SYN1:
  1724.     MOV    AL,20H
  1725.     STOSB
  1726.     INC    CX
  1727. ;
  1728. GET_SYN2:
  1729.     LODSB
  1730.     CMP    AL,0
  1731.     JE    GET_SYN3
  1732.     STOSB
  1733.     INC    CX
  1734.     JMP    GET_SYN2
  1735. ;
  1736. GET_SYN3:
  1737.     MOV    AL,0DH
  1738.     STOSB
  1739.     MOV    AL,0AH
  1740.     STOSB
  1741.     ADD    CX,2
  1742.     MOV    AX,1
  1743.     PUSH    AX
  1744.     MOV    DI,OFFSET PRINT_LINE
  1745.     PUSH    DS
  1746.     PUSH    DI
  1747.     PUSH    CX
  1748.     PUSH    DS
  1749.     MOV    AX,OFFSET WRITTEN
  1750.     PUSH    AX
  1751.     CALL    DOSWRITE
  1752. ;
  1753.     CMP    BYTE PTR [SI],0FFH
  1754.     JE    GET_SYN4
  1755. ;
  1756.     MOV    CX,0
  1757.     JMP    GET_SYN
  1758. ;
  1759. GET_SYN4:
  1760.     POP    DS
  1761.     POP    ES
  1762.     POP    DI
  1763.     POP    SI
  1764.     POP    DX
  1765.     POP    CX
  1766.     POP    BX
  1767.     POP    BP
  1768.     MOV    AX,0
  1769.     RET
  1770. ;
  1771. NO_SYN_LIST:
  1772.     POP    DS
  1773.     POP    ES
  1774.     POP    DI
  1775.     POP    SI
  1776.     POP    DX
  1777.     POP    CX
  1778.     POP    BX
  1779.     POP    BP
  1780.     MOV    AX,1
  1781.     RET
  1782. ;
  1783. NO_SYN_LIST2:
  1784.     POP    DS
  1785.     POP    ES
  1786.     POP    DI
  1787.     POP    SI
  1788.     POP    DX
  1789.     POP    CX
  1790.     POP    BX
  1791.     POP    BP
  1792.     MOV    AX,2
  1793.     RET
  1794. ;
  1795. LIST_SYN ENDP
  1796.     
  1797.  
  1798. ;
  1799. ; ON ENTRY TO ALIAS BOTH DS AND ES POINT TO LBUFF
  1800. ;    WE WANT TO SET ES TO SYN AND SCAN THROUGH SBUFFER TO FIND A
  1801. ;    MATCHING ALIAS.  IF FOUND WE WILL COPY THAT BACK TO THE CALLING
  1802. ;    ROUTINE ALONG WITH THE REMAINDER OF WORKBUFF
  1803. ;
  1804.     ASSUME    CS:KEYREP, DS:LBUFF, ES:SBUFF
  1805. ALIAS    PROC
  1806.     PUSH    BX
  1807.     PUSH    CX
  1808.     PUSH    DX
  1809.     PUSH    SI
  1810.     PUSH    DI
  1811.     PUSH    DS
  1812.     PUSH    ES
  1813.     MOV    SI,OFFSET WORKBUFF
  1814.     PUSH    SI
  1815.     MOV    CX,0
  1816. FIND_END:
  1817.     LODSB
  1818.     INC    CX
  1819.     CMP    AL,' '
  1820.     JE    FOUND_END
  1821.     CMP    AL,0DH
  1822.     JNE    FIND_END
  1823. FOUND_END:
  1824.     DEC    CX
  1825.     POP    SI
  1826.                 ; SI POINTS TO SOURCE TO MATCH
  1827.                 ; CX IS LENGTH TO MATCH
  1828.                 ; ACTUALLY [SI+CX] == ' '
  1829.     MOV    AX,SEG SBUFF
  1830.     MOV    ES,AX
  1831.     MOV    DX,SYNLEN
  1832.     DEC    DX
  1833.     MOV    DI,ES:SYNHEAD    ; START OF SYNBUFF IN ES
  1834.     CMP    DI,ES:SYNTAIL    ; ANYTHING IN BUFFER?
  1835.     JE    NOSYN        ; NO
  1836.     CALL    CMPSTR        ; YES, GO LOOKING
  1837.     CMP    AX,0
  1838.     JE    GOTSYN
  1839.     JMP    NOSYN
  1840. ;
  1841. ; AT GOTSYN, WE FOUND AN ALIAS. ES:DI POINTS TO START OF REPLACEMENT
  1842. ;    DS:SI STILL POINTS TO START OF SOURCE AND CX STILL CONTAINS
  1843. ;    LENGTH OF SOURCE
  1844. ;
  1845. GOTSYN:    MOV    BX,DI        ; BX POINTS TO REPLACEMENT
  1846.     MOV    DI,OFFSET XMITBUFF
  1847.     MOV    AX,ES
  1848.     PUSH    DS
  1849.     POP    ES
  1850.     MOV    DS,AX
  1851. ;
  1852. ALOOP4:    MOV    AL,[BX]        ; REPLACEMENT IN DS:[BX]
  1853.     CMP    AL,0        ; XMITBUFF IN ES:[DI]
  1854.     JE    ALOOP5
  1855.     STOSB
  1856.     INC    BX
  1857.     AND    BX,SYNLEN-1
  1858.     JMP    ALOOP4
  1859. ;
  1860. ALOOP5:    PUSH    ES
  1861.     POP    DS        ; DS NOW POINTS TO BOTH WORKBUFF AND XMITBUFF
  1862.     ADD    SI,CX
  1863. ;
  1864. ALOOP6:    LODSB
  1865.     CMP    AL,0DH
  1866.     JE    ALOOP7
  1867.     STOSB
  1868.     JMP    ALOOP6
  1869. ;
  1870. ALOOP7:    STOSB
  1871.     POP    ES
  1872.     POP    DS
  1873.     POP    DI
  1874.     POP    SI
  1875.     POP    DX
  1876.     POP    CX
  1877.     POP    BX
  1878.     MOV    AX,0
  1879.     JMP    ALOOPDONE
  1880. ;
  1881. NOSYN:
  1882.     POP    ES
  1883.     POP    DS
  1884.     POP    DI
  1885.     POP    SI
  1886.     POP    DX
  1887.     POP    CX
  1888.     POP    BX
  1889.     MOV    AX,1
  1890. ;
  1891. ALOOPDONE:
  1892.     RET
  1893.  
  1894. ALIAS    ENDP
  1895.  
  1896. ;
  1897. ; CMPSTR IS A ROUTINE TO COMPARE A SOURCE STRING IN DS:SI OF LENGTH CX
  1898. ;    TO A SET OF STRINGS IN A CIRCULAR BUFFER ES:DI OF LENGTH DX+1.
  1899. ;    THE STRINGS ARE FORMED AS STRINGA,0FFH,STRINGB,0H.  WE ATTEMPT TO
  1900. ;    MATCH THE SOURCE STRING WITH STRINGA. THE FINAL STRING SET IS
  1901. ;    TERMINATED WITH A 0H AND A 0FFH.
  1902. ;    ON RETURN, IF AX==0 MATCH FOUND AND DI POINTS TO REPLACEMENT.
  1903. ;        IF AX == 1 NO MATCH FOUND AND DI POINTS TO END OF BUFFER.
  1904. ;
  1905. CMPSTR    PROC    NEAR
  1906.     PUSH    SI
  1907.     PUSH    CX
  1908.     
  1909. S_LOOP:    LODSB
  1910.     CMP    AL,61H
  1911.     JL    S_LOOP1
  1912.     CMP    AL,7AH
  1913.     JG    S_LOOP1
  1914.     SUB    AL,20H
  1915. S_LOOP1:
  1916.     MOV    AH,AL
  1917.     MOV    AL,ES:[DI]
  1918.     CMP    AL,61H
  1919.     JL    S_LOOP2
  1920.     CMP    AL,7AH
  1921.     JG    S_LOOP2
  1922.     SUB    AL,20H
  1923. S_LOOP2:
  1924.     CMP    AL,AH
  1925.     JNE    NO_MATCH
  1926.     INC    DI
  1927.     AND    DI,DX
  1928.     LOOP    S_LOOP
  1929. E_LOOP:    CMP    BYTE PTR ES:[DI],0FFH
  1930.     JE    FOUND_MATCH
  1931.     JMP    NO_MATCH1
  1932. NO_MATCH:
  1933.     INC    DI
  1934.     AND    DI,DX
  1935. NO_MATCH1:
  1936.     CMP    BYTE PTR ES:[DI],0
  1937.     JNE    NO_MATCH
  1938.     INC    DI
  1939.     AND    DI,DX
  1940.     CMP    BYTE PTR ES:[DI],0FFH
  1941.     JE    FAIL
  1942.     POP    CX
  1943.     POP    SI
  1944.     PUSH    SI
  1945.     PUSH    CX
  1946.     JMP    S_LOOP
  1947. ;
  1948. FOUND_MATCH:
  1949.     POP    CX
  1950.     POP    SI
  1951.     INC    DI
  1952.     MOV    AX,0
  1953.     RET
  1954. ;
  1955. FAIL:    POP    CX
  1956.     POP    SI
  1957.     MOV    AX,1
  1958.     RET
  1959.  
  1960. CMPSTR    ENDP
  1961.  
  1962.  
  1963. KEYREP    ENDS
  1964. END    START
  1965.  
  1966.