APP   Ellipsis
IN    -
OUT   DotDotDot
TYPE  Module

PRE
 `delay=5
END PRE

DEFINE WORKSPACE
  Name     workspace
  Default  r12
   `count    !     Count of number of .'s
   `pointer  !     pointer to next character to output
END WORKSPACE

DEFINE MODULE
  Name     : Ellipsis
  Version  : 1.01
  Date     : 12 Nov 1995
  Author   : Justin Fletcher
  Help     :  Conversion
  Init     : initialise
  Final    : finalise
  Commands
    Name   : Ellipsis
    Help   : ...
             The Ellipsis module provides a special key sequence to
             add  into the keyboard buffer. Press . three times to
             activate.
  End Commands
  Workspace  `len_workspace
END MODULE

.initialise
    STMFD   (sp)!,{link}
    MOV     r0,#&14               ; vector &14 - insert vector
    ADR     r1,insvector          ; to be processed at insvector
    XSWI    "XOS_Claim",,,r12
    MOV     r0,#0
    STRW    r0,`count
    LDMFD   (sp)!,{pc}

.finalise
    STMFD   (sp)!,{r0-r2,link}
    MOV     r0,#&14               ; vector &14 - insert vector
    ADR     r1,insvector          ; to be processed at insvector
    XSWI    "XOS_Release",,,r12
    LDMFD   (sp)!,{r0-r2,pc}

.insvector
    STMFD   (sp)!,{r1-r2,r8-r9,link}
    CMP     r1,#0                 ; is it insert vector ?
    BNE     $exit                 ; if not, forget it
    LDRW    r2,`count             ; get the count
    CMP     r0,#ASC(".")          ; is it a . insert ?
    ADDEQ   r2,r2,#1              ; if so, inc count
    MOVNE   r2,#0                 ; otherwise, zero count
    CMP     r2,#3                 ; is it 3 ?
    MOVEQ   r2,#0                 ; if so, reset to zero
    STRW    r2,`count             ; store count back
    BNE     $exit                 ; if not 3rd, exit
    ADR     r0,$tosend            ; pointer to data to send
    STRW    r0,`pointer           ; store in workspace
    MOV     r0,#`delay            ; call every x cs
    ADR     r1,callbackroutine    ; the address of the code
    MOV     r2,r12                ; workspace
    MODE    +svc,r6,r7            ; set SVC mode and stack link
    SWI     "OS_CallAfter"        ; setup call back
    MODE    -svc,r6,r7            ; release SVC mode and unstack link
    LDMFD   (sp)!,{r1-r2,r8-r9,link,pc} ; return without adding anything to insert
$exit
    LDMFD   (sp)!,{r1-r2,r8-r9,pc}

$tosend
;     EQUS    "ABCD"+CHR$2
    EQUB    127
    EQUB    127
    EQUB    0
    EQUB    ASC("")
    EQUB    2
    ALIGN

.callbackroutine
    STMFD   (sp)!,{r0-r4,r8-r9,link}            ; Stack registers
    MODE    +svc                          ; set SVC mode and stack link
    LDRW    r3,`pointer                   ; get pointer to char
$next
    LDRB    r4,[r3]                       ; get character
;     REM     "%r2"
    ADD     r3,r3,#1                      ; add 1 to pointer
    CMP     r4,#2                         ; is character 2 (EOL) ?
    BEQ     $remove                       ; y=remove callback
    MOV     r2,r4
    XSWI    "XOS_Byte",153,0              ; insert into buffeer
    CMP     r4,#0                         ; is it control ?
    BEQ     $next                         ; if so, get next
    STRW    r3,`pointer                   ; store back in workspace
    MOV     r0,#`delay
    ADR     r1,callbackroutine
    XSWI    "XOS_CallAfter",,,r12
$exit
$remove
    MODE    -svc                          ; release SVC mode and unstack link
    LDMFD   (sp)!,{r0-r4,r8-r9,pc}              ; Return from call

#Post
#Run <CODE>
