; 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