Files

280 lines
4.9 KiB
NASM

; Planned commands:
; [ ] i insert
; [ ] a append
; [-] d delete
; [x] l prints lines
; [ ] w save to disk
; [x] q quit
ed:
pusha
call determine_line_count
.main_loop:
; CLEAR VARIABLES
mov [ed_start_int], 0
mov [ed_end_int], 0
mov [ed_operation_from], 0
mov [ed_operation_by], 0
; Setup prompt
mov ax, ed_prompt
mov bx, 40
call keyboard_display_input ; AX = string location, BX = max prompt length
cmp bx, 1 ; I user pressed escape
je .quit
mov si, ed_prompt
mov bx, 0 ; Keeps track of whether comma has passed
jmp .get_token
.error:
call ed_error
jmp .main_loop
; Types of tokens:
; Number: eg 123
; Doller (refers to the last line) $
; Comma ,
; Command: eg i
; eg 123,127i
.get_token:
lodsb
; COMMA
cmp al, ','
je .comma
; DOLLAR SIGN
cmp al, '$'
je .dollar
; NUMBER
call check_is_number
jc .get_number_token
; COMMAND
call check_is_letter
jc .get_letter_token
jmp .error
; Assign a number to either the start or end int (start,end)
.dollar:
mov ax, [ed_line_count]
inc si ; Cancel out the last dec si
jmp .after_int_cast
.get_number_token:
dec si
call string_cast_to_int ; AX = integer, DX = length of int string
.after_int_cast:
cmp bx, 0
je .assign_start_int
jg .assign_end_int
.assign_start_int:
mov [ed_start_int], ax
jmp .after_int_assign
.assign_end_int:
mov [ed_end_int], ax
; Check it's not after the end of the file
cmp ax, [ed_line_count]
jg .error
; Check it's not less than the start int
cmp ax, [ed_start_int]
jl .error
.after_int_assign:
dec si
jmp .get_token
; Determines a command
.get_letter_token:
; If ed int
cmp [ed_end_int], 0
je .set_end_int
.after_end_int_check:
cmp al, 'l'
je .list
cmp al, 'd'
je .delete
cmp al, 'q'
je .quit
call ed_error
jmp .main_loop
; If no end int is assigned, set it to the start int
.set_end_int:
cmp bx,0
push ax
jne .end_int_to_end ; If , has been passed
.end_int_to_start_int:
mov ax, [ed_start_int]
mov [ed_end_int], ax
pop ax
jmp .after_end_int_check
.end_int_to_end:
mov ax, [ed_line_count]
mov [ed_end_int], ax
pop ax
jmp .after_end_int_check
; Changes the value from start int to end int
.comma:
mov bx, 1
jmp .get_token
; COMMANDS
; DELETE ;
.delete:
; Adjust the ed line count
mov ax,[ed_end_int]
sub ax,[ed_start_int] ; difference in the lines
inc ax
sub [ed_line_count], ax
; set up registers to shift data left
; Get the byte of where the left shift will start
mov bx, [ed_end_int]
inc bx
call get_byte_of_line ; CX = byte of start of new line (relative to file buffer)
mov [ed_operation_from], cx
; Get the number of bytes to shift left by
mov bx, [ed_start_int]
call get_byte_of_line
mov ax, [ed_operation_from]
sub ax, cx
mov [ed_operation_by], ax
; Perform the shift
call shift_data_left
; Adjust the file metadata byte count
mov ax, [file_length]
sub ax, [ed_operation_by]
mov [file_length], ax
; Exit
call text_newline
jmp .main_loop
; LIST ;
.list:
; set up registers to print the data
; Get the byte of where the printing will start
mov bx, [ed_start_int]
call get_byte_of_line ; CX = byte of start of new line (relative to file buffer)
mov si, cx
; Get the number of bytes to print
mov bx,[ed_end_int]
inc bx
call get_byte_of_line
sub cx,si
call text_newline
add si, file_buffer
call text_print_raw
jmp .main_loop
.quit:
popa
jmp os_start_cli
; This could probably go in disk_?
shift_data_left:
; Calculate source pointer
mov si, [ed_operation_by]
add si, file_buffer
; Calculate destination pointer
mov di, si
sub di, [ed_operation_by]
; Loop count
mov cx, file_length ; STORES THE LENGTH OF THE FILE IN BYTES
sub cx, ed_operation_by
; Perform the actual left shift
rep movsb
; Override the rest with zeroes
mov cx, [ed_operation_by]
mov al, 0
rep stosb
ret
ed_error:
pusha
call text_newline
mov ah, 0Eh
mov al, '?'
int 10h
call text_newline
popa
ret
; IN: BX = target line
; OUT: CX = relative byte
; TODO fix
get_byte_of_line:
push dx
push si
push ax
mov si, file_buffer
xor dx,dx
xor cx,cx
jmp .increment_line_count
.line_loop:
xor ax,ax
lodsb
inc cx
cmp al, 0Ah
je .increment_line_count
jmp .line_loop
.increment_line_count:
inc dx
cmp dx, bx
jl .line_loop
jmp .exit
.exit:
pop ax
pop si
pop dx
ret
determine_line_count:
mov si, file_buffer
mov dx, file_length ; STORES THE LENGTH OF THE FILE IN BYTES
xor cx,cx
.line_count_loop:
lodsb
cmp al, 0Ah
je .increment_line_count
dec dx
cmp dx, 0
jg .line_count_loop
mov [ed_line_count], cx
ret
.increment_line_count:
inc cx
jmp .line_count_loop
ed_data_start: db "ED IS COOL"
ed_prompt: times 40 db 0
ed_start_int: dw 1
ed_end_int: dw 0
ed_line_count: dw 0
ed_operation_from: dw 0
ed_operation_by: dw 0
ed_tmp: dd 0