; asm rewrites of functions originally written in C, for edbox.c.
; old C code here as comments, for reference.

 .export _edbox_addchr, _edbox_space, _edbox_set, _edbox_clear
 .export _hide_cursor, _show_cursor, _storechr
 .export _copy_to_old, _restore_old, _backspace, _inschr
 .import _edbox_len, _edbox_pos, _old_edbox, _old_len, _typeover
 .import _del_char, _bell, _move_right
 .importzp ptr1

 ; EDBOX_SIZE + 1, see edbox.h
 EDBOX_SIZE_PLUS_1 = $f1
 EDBOX_SIZE = $f0
 EDBOX_MAXPOS = $ef

 EDBOX_ADDR = $0600 ; MUST agree with EDBOX_ADDR from addrs.h!

; this compiled to like 31 bytes of code...
; this version is 7 bytes.
;; void storechr(char c) {
;; 	edit_box[edbox_pos] = c;
;; }
_storechr:
 ldx _edbox_pos
 sta EDBOX_ADDR,x
 rts

;; void hide_cursor(void) {
;; 	edit_box[edbox_pos] &= 0x7f;
;; }
_hide_cursor:
 ldx _edbox_pos
 lda EDBOX_ADDR,x
 and #$7f
store_curs:
 sta EDBOX_ADDR,x
 rts

;; void show_cursor(void) {
;; 	edit_box[edbox_pos] |= 0x80;
;; }
_show_cursor:
 ldx _edbox_pos
 lda EDBOX_ADDR,x
 ora #$80
 bne store_curs

;; static void copy_to_old(void) {
;; 	if(!edbox_len) return;
;; 	memcpy(old_edbox, edit_box, edbox_len);
;; 	bzero(old_edbox + edbox_len, EDBOX_MAXPOS - edbox_len);
;; 	old_len = edbox_len;
;; }
_copy_to_old:
 lda _edbox_len
 beq nope
 ldx #0
@l:
 lda EDBOX_ADDR,x
 sta _old_edbox,x
 inx
 cpx #EDBOX_SIZE
 bne @l
 lda _edbox_len
 sta _old_len
nope:
 rts

;; static void restore_old(void) {
;; 	edbox_clear();
;; 	hide_cursor();
;; 	memcpy(edit_box, old_edbox, old_len);
;; 	edbox_pos = edbox_len = old_len;
;; }
_restore_old:
 lda _old_len
 beq nope
 ldx #0
@l:
 lda _old_edbox,x
 sta EDBOX_ADDR,x
 inx
 cpx #EDBOX_SIZE
 bne @l
 lda _old_len
 sta _edbox_len
 sta _edbox_pos
 rts

;; static void backspace(void) {
;; 	if(!edbox_pos) return;
;; 	edbox_pos--;
;; 	if(typeover)
;; 		edit_box[edbox_pos] = ' ';
;; 	else
;; 		del_char();
;; }
_backspace:
 lda _edbox_pos
 beq @nope
 dec _edbox_pos
 lda _typeover
 bne @spc
 jmp _del_char
@spc:
 lda #$20
 ldx _edbox_pos
 sta EDBOX_ADDR,x
@nope:
 rts

;; void inschr(char c) {
;; 	if(edbox_len == EDBOX_MAXPOS) {
;; 		/* buffer full, can't insert */
;; 		bell();
;; 		return;
;; 	}
;; 	move_right();
;; 	edbox_len++;
;; 	storechr(c);
;; 	edbox_pos++;
;; }
_inschr:
 pha
 lda _edbox_len
 cmp #EDBOX_MAXPOS
 bne @ok
 pla
 jmp _bell
@ok:
 jsr _move_right
 inc _edbox_len
 pla
 jsr _storechr
 inc _edbox_pos
 rts

;; void edbox_clear(void) {
;; 	bzero(edit_box, EDBOX_SIZE + 1);
;; 	edbox_pos = edbox_len = 0;
;; 	show_cursor(); // not needed? seems it is..
;; }

_edbox_clear:
 ldx #0
 txa
@l:
 sta EDBOX_ADDR,x
 inx
 cpx #EDBOX_SIZE_PLUS_1
 bne @l
 sta _edbox_pos
 sta _edbox_len
 jmp _show_cursor

;; void edbox_space(void) {
;; 	edbox_addchr(' ');
;; }
_edbox_space:
 lda #$20
 ; fall thru...

;; void edbox_addchr(char c) {
;; 	edit_box[edbox_len++] = c;
;; 	edbox_pos = edbox_len;
;; }

_edbox_addchr:
 ldx _edbox_len
 sta EDBOX_ADDR,x
 inx
 stx _edbox_len
 stx _edbox_pos
 rts

;; void edbox_set(char *contents) {
;; 	edbox_clear();
;; 	while(*contents) {
;; 		edit_box[edbox_len++] = *contents++;
;; 	}
;; 	edbox_pos = edbox_len;
;; }

; notice the asm version does bounds checking, which the C version
; didn't do.
_edbox_set:
 sta ptr1
 stx ptr1+1
 jsr _edbox_clear
 ldy #0
@l:
 lda (ptr1),y
 sta EDBOX_ADDR,y
 beq @done ; if we hit a 0 byte in the input, we're done
 inx
 iny
 cpy #EDBOX_SIZE_PLUS_1 ; if we hit the edbox size limit, we're done
 bne @l
 dey
@done:
 sty _edbox_len
 sty _edbox_pos
 rts
