BITS 16 %define svim_starting_row_number_for_text 2 %define svim_end_row_number_for_text 24 %define svim_magic_buffer_size 2048 svim: pusha ; save state before program sub sp, svim_magic_buffer_size mov [buffer_for_svim_base_left_of_cursor], sp sub sp, svim_magic_buffer_size mov [buffer_for_svim_base_right_of_cursor], sp mov bx, sp mov BYTE [bx], 0 ; be sure that the first byte is zero. mov WORD [svim_counter_char_in_left_buffer], 0 ; reset these to zero mov WORD [svim_counter_char_in_right_buffer], 0 mov WORD [svim_get_cursor_distance_to_next_line_break], 0 mov BYTE [svim_save_on_exit], 0 call os_clear_screen xor bx, bx mov ah, 0x02 mov bh, 0x00 ; page number 0 mov dh, 0x00 ; row zero mov dl, 0x17 ; coloumn zero int 0x10 mov si, welcome_svim_select_file call print call printCRLF mov si, seperate_line call print call vsfs_list_files_command ; move cursor to the bootom xor ax, ax xor bx, bx mov ah, 0x02 mov bh, 0x00 ; page number 0 mov dh, 0x17 ; row zero mov dl, 0x00 ; coloumn zero int 0x10 mov si, welcome_svim call print call printCRLF mov si, welcome_svim_enter_fileindex call print ; Ask the user for the filename xor bx, bx xor cx, cx ; are going to be the counter xor dx, dx .enter_fileindex_loop: push cx .loop_no_push: mov ax, 0x10 ; BIOS call to wait for key int 0x16 cmp ax, 0x1c0d ; enter key je .fileindex_done cmp ax, 0x0e08 ; backspace jne .no_enter_fileindex cmp cx, 0 je .loop_no_push pop cx sub cx, 1 mov bx, [buffer_for_svim_base_left_of_cursor] add bx, cx mov BYTE [bx], 0 ; Go back one space mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character. int 0x10 ; Place a NULL mov al, 0x0 ; NULL int 0x10 ; Go back one space again as the above print of NULL pushes the cursor forward again. mov ax, 0x0e08 int 0x10 jmp .enter_fileindex_loop .no_enter_fileindex: mov bh, 0x00 mov bl, 0x02 mov ah, 0x0E int 0x10 ; print char pop cx mov bx, [buffer_for_svim_base_left_of_cursor] add bx, cx mov [bx], al add cx, 1 ; fileindex must only be 120 chars cmp cx, 120 jae .fileindex_done jmp .enter_fileindex_loop .fileindex_done: pop cx ; Cleanup, and now contain filename size mov ax, cx add ax, [buffer_for_svim_base_left_of_cursor] mov bx, ax mov BYTE [bx], 0 mov si, [buffer_for_svim_base_left_of_cursor] call zstring_to_integer ; ax now contain the interger index for the file mov [fileindex_for_open_file], ax ; save the file index call svim_redraw_window ; LOAD FILE ; Prepare to ask the filesystem to load the file ; The file system should be given the file_id and the buffer where we can write mov ax, [fileindex_for_open_file] mov ch, al ; move the fileindex in the ch mov bx, ds mov es, bx mov bx, [buffer_for_svim_base_left_of_cursor] mov ah, 0x02 ;Read sectors from drive mov al, 0x04 ;Number of sectors to read (8 * 512 = 4096 bytes) mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) mov dh, 0x00 ;Head number mov dl, [global_disk_identifier] ;Drive number int 0x13 mov bx, [buffer_for_svim_base_left_of_cursor] add bx, 2046 mov ax, [bx] mov [svim_counter_char_in_left_buffer], ax .svim_loop: ; Redraw the whole text, ; move cursor to the top, where the text has to start (line 2) xor ax, ax xor bx, bx mov ah, 0x02 mov bh, 0x00 ; page number 0 mov dh, 0x02 ; row mov dl, 0x00 ; coloumn int 0x10 mov ax, [svim_counter_char_in_left_buffer] mov si, [buffer_for_svim_base_left_of_cursor] call print ; Check if there is somthing to the right of the cursor that should be written to screen mov cx, [svim_counter_char_in_right_buffer] cmp cx, 0 ; Nothing to be written je .no_write_right_of_the_cursor call get_cursor_position push dx mov bx, [buffer_for_svim_base_right_of_cursor] dec bx mov cx, [svim_counter_char_in_right_buffer] call print_reverse pop dx xor ax, ax xor bx, bx mov ah, 0x02 mov bx, 0x00 ; page zero int 0x10 .no_write_right_of_the_cursor: xor bx, bx xor cx, cx xor dx, dx mov ax, 0x1000 ; BIOS call to wait for key int 0x16 cmp ax, 0x1c0d ; enter key jne .no_enter mov bx, [buffer_for_svim_base_left_of_cursor] add bx, [svim_counter_char_in_left_buffer] mov BYTE [bx], 13 ; put char in the buffer mov BYTE [bx + 1], 10 ; put char in the buffer mov bx, [svim_counter_char_in_left_buffer] add bx, 0x02 mov [svim_counter_char_in_left_buffer], bx call svim_redraw_window jmp .svim_loop .no_enter: cmp ax, 0x4be0 ; left key jne .check_up_key call handle_left_key_pressed jmp .svim_loop .check_up_key: cmp ax, 0x48e0 ; up key jne .check_right_key call handle_up_key_pressed jmp .svim_loop .check_right_key: cmp ax, 0x4de0 ; right key jne .check_down_key call handle_right_key_pressed jmp .svim_loop .check_down_key: cmp ax, 0x50e0 ; down key jne .check_tab_key call handle_down_key_pressed jmp .svim_loop .check_tab_key: cmp ax, 0x0f09 ; tab key jne .no_special_key_pressed mov bx, [buffer_for_svim_base_left_of_cursor] add bx, [svim_counter_char_in_left_buffer] mov BYTE [bx], 0x20 ; put space char in the buffer mov BYTE [bx + 1], 0x20 ; put space char in the buffer mov bx, [svim_counter_char_in_left_buffer] add bx, 0x02 mov [svim_counter_char_in_left_buffer], bx call svim_redraw_window jmp .svim_loop jmp .svim_loop .no_special_key_pressed: cmp ax, 0x11b ; ESC key je .end_svim cmp ax, 0x3c00 ; f2 key je .f2_key_pushed cmp ax, 0x3d00 ; f3 key je .f3_key_pushed cmp ax, 0x0e08 ; backspace je .backspace_pushed mov bx, ax mov ax, 0xe20 mov al, bl mov bx, [buffer_for_svim_base_left_of_cursor] add bx, [svim_counter_char_in_left_buffer] mov [bx], al ; put char in the buffer mov bx, [svim_counter_char_in_left_buffer] add bx, 0x01 mov [svim_counter_char_in_left_buffer], bx int 0x10 ; print char jmp .svim_loop .end_svim: mov ax, [svim_counter_char_in_right_buffer] .copy_data_to_left_buffer: cmp ax, 0 je .stop_copy call handle_right_key_pressed dec ax jmp .copy_data_to_left_buffer .stop_copy: mov dl, [svim_save_on_exit] test dl, dl ; if zero qiut without exit jz .svim_quit ; save the written buffer ;AH 03h ;AL Sectors To Write Count ;CH Track ;CL Sector ;DH Head ;DL Drive ;ES:BX Buffer Address Pointer mov ax, [svim_counter_char_in_left_buffer] mov bx, [buffer_for_svim_base_left_of_cursor] add bx, 2046 mov [bx], ax mov bx, ds mov es, bx mov bx, [buffer_for_svim_base_left_of_cursor] mov ax, [fileindex_for_open_file] mov ch, al ; move the fileindex in the ch mov ah, 0x03 ;Write sectors to drive mov al, 0x04 ;Number of sectors to write (8 * 512 = 4096 bytes) mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7) mov dh, 0x00 ;Head number mov dl, [global_disk_identifier] ;Drive number int 0x13 ;Low level disk services ; clean up swim ;xor bx, bx ;xor cx, cx ; Upper and left coordinate ;mov bh, 0x0f ; color for new screen 0 = black f = white ;mov dh, 0xff ; Select all screen ;mov dl, 0xff ; Select all screen ;mov ah, 0x07 ; scrool down ;mov al, 0x00 ; scrool 0 lines (means blank screen ) ;int 0x10 .svim_quit: call os_clear_screen add sp, svim_magic_buffer_size add sp, svim_magic_buffer_size popa ret .f2_key_pushed: mov al, 1 mov [svim_save_on_exit], al call svim_redraw_window jmp .svim_loop .f3_key_pushed: mov al, 0 mov [svim_save_on_exit], al call svim_redraw_window jmp .svim_loop .backspace_pushed: mov bx, [svim_counter_char_in_left_buffer] cmp bx, 0 je .svim_loop mov cx, bx sub cx , 1 mov bx, [buffer_for_svim_base_left_of_cursor] add bx, cx .delete_linebreak: cmp BYTE [bx], 10 jne .delete_char mov BYTE [bx], 0 ; cx is already the counter sub cx, 1 ; Substract one charecter from the buffer, CR and LF sub bx, 1 mov BYTE [bx], 0 mov [svim_counter_char_in_left_buffer], cx call svim_redraw_window jmp .svim_loop .delete_char: mov BYTE [bx], 0 mov [svim_counter_char_in_left_buffer], cx call svim_redraw_window jmp .svim_loop handle_left_key_pressed: pusha mov ax, [svim_counter_char_in_left_buffer] cmp ax, 0 je .end mov bx, [buffer_for_svim_base_left_of_cursor] add bx, ax dec bx ; Because it faces the next free spot mov dx, [bx] mov BYTE [bx], 0 push dx mov cx, [svim_counter_char_in_right_buffer] mov bx, [buffer_for_svim_base_right_of_cursor] add bx, cx mov [bx], dx inc bx mov BYTE [bx], 0 ; be sure that the next byte is always zero dec ax inc cx mov [svim_counter_char_in_left_buffer], ax mov [svim_counter_char_in_right_buffer], cx pop bx cmp bx, 10 ; check if we hit a line break. jne .end call handle_left_key_pressed ; we have hit a linebreak and need to go once more .end: popa ret handle_right_key_pressed: pusha mov ax, [svim_counter_char_in_right_buffer] cmp ax, 0 ; check if we have more on the right side of the buffer je .end ; If we don't, jump to the end and do nothing. mov bx, [buffer_for_svim_base_right_of_cursor] add bx, ax dec bx ; Because it faces the next free spot mov dx, [bx] mov BYTE [bx], 0 push dx mov cx, [svim_counter_char_in_left_buffer] mov bx, [buffer_for_svim_base_left_of_cursor] add bx, cx mov [bx], dx inc bx mov BYTE [bx], 0 ; be sure that the next byte is always zero dec ax inc cx mov [svim_counter_char_in_right_buffer], ax mov [svim_counter_char_in_left_buffer], cx pop bx cmp bx, 13 ; check if we hit a line break. jne .end call handle_right_key_pressed ; we have hit a linebreak and need to go once more .end: popa ret handle_up_key_pressed: call get_cursor_position ; Find the position of the cursor xor cx, cx mov cl, dl ; Store coulun count push cx ; save the column count. inc cx .find_first_line_break: cmp BYTE cl, 0 je .find_right_position_on_new_line call handle_left_key_pressed dec cl jmp .find_first_line_break .find_right_position_on_new_line: call svim_get_left_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break mov ax, [svim_get_cursor_distance_to_next_line_break] pop cx .move_curser_to_correct_position_on_the_new_line: cmp cx, ax jge .end call handle_left_key_pressed dec ax jmp .move_curser_to_correct_position_on_the_new_line .end: ret handle_down_key_pressed: call get_cursor_position ; Find the position of the cursor xor ax, ax mov al, dl ; Store coulun count push ax ; save the column count. call svim_get_right_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break mov cx, [svim_get_cursor_distance_to_next_line_break] .find_first_line_break: cmp cx, 0 je .find_left_position_on_new_line call handle_right_key_pressed dec cx jmp .find_first_line_break .find_left_position_on_new_line: call svim_get_right_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break mov ax, [svim_get_cursor_distance_to_next_line_break] pop cx cmp cx, ax jle .move_curser_to_correct_position_on_the_new_line mov cx, ax .move_curser_to_correct_position_on_the_new_line: cmp cx, 0 je .end call handle_right_key_pressed dec cx jmp .move_curser_to_correct_position_on_the_new_line .end: ret svim_get_left_line_count: pusha xor ax, ax ; Number of chars in the right side buffer xor cx, cx ; This is our counter to the next line break mov ax, [svim_counter_char_in_left_buffer] mov bx, [buffer_for_svim_base_left_of_cursor] add bx, ax dec bx .check_next: cmp ax, 0 ; check if we have hit the absolut beginnig of the string je .end mov BYTE dl, [bx] cmp BYTE dl, 10 ; See if we have hit an linebreak je .end_line_break dec bx ; dec one, to check the prev char, until we hit a line break. dec ax inc cx ; add one to the counter jmp .check_next .end_line_break: ;inc cx ; add one to the counter .end: mov WORD [svim_get_cursor_distance_to_next_line_break], cx popa ret svim_get_right_line_count: pusha xor ax, ax ; Number of chars in the right side buffer xor cx, cx ; This is our counter to the next line break mov ax, [svim_counter_char_in_right_buffer] mov bx, [buffer_for_svim_base_right_of_cursor] add bx, ax dec bx .check_next: cmp ax, 0 ; check if we have hit the absolut beginnig of the string je .end mov BYTE dl, [bx] cmp BYTE dl, 13 ; See if we have hit an linebreak je .end_line_break dec bx ; dec one, to check the prev char, until we hit a line break. dec ax inc cx ; add one to the counter jmp .check_next .end_line_break: inc cx ; add one to the counter .end: mov WORD [svim_get_cursor_distance_to_next_line_break], cx popa ret get_cursor_position: xor ax, ax xor bx, bx mov ah, 0x03 mov bh, 0x00 ; page number 0 int 0x10 ret svim_redraw_window: call os_clear_screen ; move cursor to the bootom xor ax, ax xor bx, bx mov ah, 0x02 mov bh, 0x00 ; page number 0 mov dh, 0x17 ; row zero mov dl, 0x00 ; coloumn zero int 0x10 mov si, seperate_line call print mov si, welcome_svim call print mov al, [svim_save_on_exit] test al, al jz .not_save_mode mov si, svim_string_save jmp .after_not_safe_mode .not_save_mode: mov si, svim_string_not_save .after_not_safe_mode: call print ; move cursor to the top xor ax, ax xor bx, bx mov ah, 0x02 mov bh, 0x00 ; page number 0 mov dh, 0x00 ; row zero mov dl, 0x00 ; coloumn zero int 0x10 ; Load from disk and, enter it, into the buffer mov si, welcome_svim_select_file call print mov ax, [fileindex_for_open_file] call dumpax10 call printCRLF mov si, seperate_line call print ret ;.f_key_pushed: ;mov al, 0x01 ;arg: index 1 ;call os_change_screen ;jmp .svim_loop ;.load_buffer_svim: svim_get_cursor_offset_on_current_line dw 0 svim_get_cursor_distance_to_next_line_break dw 0 buffer_for_svim_base_left_of_cursor dw 0 buffer_for_svim_base_right_of_cursor dw 0 svim_counter_char_in_left_buffer dw 0 svim_counter_char_in_right_buffer dw 0 seperate_line db '________________________________________________________________________________', 0 welcome_svim db 'Vim like text editor for SingOS, ESC to exit svim - ', 0 svim_string_save db 'save-mode', 0 svim_string_not_save db 'not-save-mode', 0 welcome_svim_select_file db 'svim v0.2.0 - Open file: ', 0 welcome_svim_enter_fileindex db 'Enter fileindex: ', 0 fileindex_for_open_file dw 0 svim_total_file_size_counter dw 0 svim_save_on_exit db 0