diff --git a/README.md b/README.md index 6ea3ac4..83c6064 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,6 @@ installation option, for your safety. ### Basic stuff -* be able to click on asm/text files in file listing to open * delete the TODO from release README ### Nice to have diff --git a/ponydos_static.inc b/ponydos_static.inc index 7775791..990e5cf 100644 --- a/ponydos_static.inc +++ b/ponydos_static.inc @@ -16,6 +16,7 @@ WM_PAINT equ 0 WM_MOUSE equ 1 WM_KEYBOARD equ 2 WM_UNHOOK equ 3 +WM_OPEN_FILE equ 4 MOUSE_PRIMARY equ 0x01 MOUSE_SECONDARY equ 0x02 diff --git a/shell.asm b/shell.asm index b24b9f9..cdf639f 100644 --- a/shell.asm +++ b/shell.asm @@ -181,7 +181,7 @@ paint: call get_window mov bx, [si + window.next] - call forward_event + call send_event cmp si, windows + WINDOW_ID_FILE_WINDOW*window.size jne .not_file_window @@ -308,7 +308,7 @@ mouse: mov cx, 0xffff mov bx, [si + window.next] mov al, WM_MOUSE - call forward_event + call send_event ret .outside: @@ -316,7 +316,7 @@ mouse: pop cx mov bx, [si + window.next] mov al, WM_MOUSE - call forward_event + call send_event ret ; in: @@ -442,10 +442,10 @@ unhook: ; Forward the event mov bx, [si + window.next] - call forward_event + call send_event ; Update next ID - ; If window.next was zero, forward_event will also return zero so + ; If window.next was zero, send_event will also return zero so ; this is safe in all cases mov [si + window.next], ax @@ -542,49 +542,129 @@ move: pop dx ret +; ------------------------------------------------------------------ +; Launching +; ------------------------------------------------------------------ + ; out: ; clobbers everything launch: mov si, launch_filename - ; Is it a .wall file? + ; 4 letter file extension? call strlen cmp cx, 5 - jb .not_wall + jb .less_than_5_chars add si, cx sub si, 5 + ; .text + mov di, text_extension + call strcmp + je .text_file + ; .wall mov di, wall_extension call strcmp - jne .not_wall + je .wallpaper + .less_than_5_chars: - mov ax, cs - mov es, ax - mov si, launch_filename - mov di, wallpaper_name - mov cx, FS_DIRENT_NAME_SIZE - rep movsb - - call set_wallpaper - call request_redraw - jmp .end - - .not_wall: - - ; Is it a .bin file? + ; 3 letter file extension? cmp cx, 4 jb .not_launchable ; No, too short mov si, launch_filename add si, cx sub si, 4 + ; .asm + mov di, asm_extension + call strcmp + je .text_file + ; .txt + mov di, txt_extension + call strcmp + je .text_file + ; .bin mov di, bin_extension call strcmp - jne .not_launchable ; No, wrong extension + jne .not_launchable ; No extension matched mov si, launch_filename + call launch_binary + + ret + + .wallpaper: + mov ax, cs + mov es, ax + mov si, launch_filename + mov di, wallpaper_name + mov cx, FS_DIRENT_NAME_SIZE + rep movsb + + call set_wallpaper + call request_redraw + + ret + + .not_launchable: + ; Copy filename into the launch error dialog + mov si, launch_filename + call show_launch_error + ret + + .text_file: + ; Launch viewer.bin if it exists + mov si, viewer_file_name + call launch_binary + jc .viewer_not_found + + ; Send the WM_OPEN_FILE event to tell viewer the file we + ; want it to open. launch_binary returned its segment in bx + ; so we can just pass that to send_event, as window IDs are + ; of the form segment | internal_id. + mov al, WM_OPEN_FILE + mov cx, launch_filename + call send_event + + .viewer_not_found: + ret + +; in: +; si = name of file not launchable +; out: +; clobbers everything +show_launch_error: + mov di, launch_error_dialog.filename + mov cx, FS_DIRENT_NAME_SIZE-1 + mov ah, 0xf0 + .copy: + lodsb + test al, al + je .copy_end + stosw + loop .copy + .copy_end: + ; Zero out the rest + xor al, al + rep stosw + + ; Show dialog + mov ax, cs + add ax, WINDOW_ID_LAUNCH_ERROR + mov si, windows + WINDOW_ID_LAUNCH_ERROR*window.size + call show_window + + ret + +; in: +; si = name of the binary to launch +; out: +; cf = error occured when launching binary +; bx = segment of the launched binary +; clobbers everything else +launch_binary: mov dx, 1 ; Don't create a new file if not found call PONYDOS_SEG:SYS_OPEN_FILE test ax, ax - jz .not_launchable + jz .file_not_found push ax push cx @@ -600,14 +680,7 @@ launch: jz .found_free_segment inc si loop .find_free_segment - ; Display an error dialog if we can't allocate a segment - mov ax, cs - add ax, WINDOW_ID_OOM_ERROR - mov si, windows + WINDOW_ID_OOM_ERROR*window.size - call show_window - pop cx - pop ax - jmp .end + jmp .out_of_memory .found_free_segment: mov byte [es:si], 1 ; Mark as used @@ -623,34 +696,37 @@ launch: xor di, di ; Read call PONYDOS_SEG:SYS_MODIFY_SECTORS + push es ; Save the segment for return value + ; Transfer control to the newly loaded binary push cs ; Return segment - mov ax, .end + mov ax, .success push ax ; Return offset push es ; Call segment mov ax, PROC_INITIALIZE_ENTRYPOINT push ax ; Call offset retf - .end: + .success: + pop bx + clc ret - .not_launchable: - ; Copy filename into the launch error dialog - mov si, launch_filename - mov di, launch_error_dialog.filename - mov cx, FS_DIRENT_NAME_SIZE-1 - .loop: - lodsb - stosb - inc di - loop .loop + .file_not_found: + call show_launch_error + jmp .error - ; Show dialog + .out_of_memory: + ; Display an error dialog if we can't allocate a segment mov ax, cs - add ax, WINDOW_ID_LAUNCH_ERROR - mov si, windows + WINDOW_ID_LAUNCH_ERROR*window.size + add ax, WINDOW_ID_OOM_ERROR + mov si, windows + WINDOW_ID_OOM_ERROR*window.size call show_window + pop cx + pop ax + + .error: + stc ret ; out: @@ -675,7 +751,7 @@ set_wallpaper: ; bx = window ID ; out: ; ax = return value of event handler; 0 if window ID is 0 -forward_event: +send_event: push bp cmp bx, 0 @@ -796,7 +872,7 @@ unhook_window: mov bx, [es:GLOBAL_WINDOW_CHAIN_HEAD] mov al, WM_UNHOOK - call forward_event + call send_event mov [es:GLOBAL_WINDOW_CHAIN_HEAD], ax @@ -1130,14 +1206,20 @@ strcmp: ret ; ------------------------------------------------------------------ -; Variables +; Constants ; ------------------------------------------------------------------ +asm_extension db '.asm', 0 bin_extension db '.bin', 0 +txt_extension db '.txt', 0 +text_extension db '.text', 0 wall_extension db '.wall', 0 -wallpaper_name db 'ponydos.wall' - times FS_DIRENT_NAME_SIZE-12 db 0 +viewer_file_name db 'viewer.bin', 0 + +; ------------------------------------------------------------------ +; Variables +; ------------------------------------------------------------------ disk_icon: db 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f @@ -1171,6 +1253,9 @@ windows: open_windows db 0 +wallpaper_name db 'ponydos.wall' + times FS_DIRENT_NAME_SIZE-12 db 0 + launch_filename times FS_DIRENT_NAME_SIZE db 0 section .bss diff --git a/viewer.asm b/viewer.asm index 27f5d73..1bdc08f 100644 --- a/viewer.asm +++ b/viewer.asm @@ -51,9 +51,14 @@ process_event: push es ; On entry, ds and es will not be set correctly for us - mov bp, cs - mov ds, bp - mov es, bp + ; WM_OPEN_FILE needs ds to be left-as is + cmp al, WM_OPEN_FILE + je .no_set_ds + push cs + pop ds + .no_set_ds: + push cs + pop es cmp al, WM_PAINT jne .not_paint @@ -79,7 +84,21 @@ process_event: jmp .end .not_unhook: + cmp al, WM_OPEN_FILE + jne .not_open_file + call event_open_file + ; Set ds in case event_open_file didn't + push cs + pop ds + jmp .end + .not_open_file: + .end: + cmp byte [exiting], 0 + je .not_exiting + call deallocate_own_memory + .not_exiting: + pop es pop ds pop bp @@ -579,7 +598,7 @@ event_click: jne .not_cancel .cancel: call unhook_self_from_window_chain - call deallocate_own_memory + mov byte [exiting], 1 jmp .end .not_cancel: cmp byte [bx], OK_COLOR @@ -735,6 +754,37 @@ event_unhook: mov ax, [window_next] ret +; in: +; al = WM_OPEN_FILE +; ds:cx = filename +; out: +; clobbers everything +event_open_file: + ; Copy the file name over + mov si, cx + mov di, [es:cur_filename_address] + .copy_filename: + lodsb + test al, al + jz .copy_end + + stosb + inc di + jmp .copy_filename + .copy_end: + mov [es:cur_filename_address], di + + ; Set ds to be as expected by most of the program + push cs + pop ds + + ; Mark that the filename came from WM_OPEN_FILE + mov byte [filename_from_wm_open_file], 1 + + call filename_ok + + ret + ; ------------------------------------------------------------------ ; Event handler subroutines ; ------------------------------------------------------------------ @@ -742,15 +792,20 @@ event_unhook: ; out: ; clobbers si, di, cx close_window: + ; If filename was from WM_OPEN_FILE event instead of user input, + ; exit the app instead of going to name input dialog + cmp byte [filename_from_wm_open_file], 0 + jne .exit_app cmp word [window.data_address], oom_window_data je .error_window cmp word [window.data_address], ood_window_data je .error_window - .not_error_window: - ; Shut off app + + .exit_app: call unhook_self_from_window_chain - call deallocate_own_memory + mov byte [exiting], 1 ret + .error_window: mov si, filename_window mov di, window @@ -1116,10 +1171,13 @@ request_redraw: ; Variables ; ------------------------------------------------------------------ +filename_from_wm_open_file db 0 +exiting db 0 + window_title times FS_DIRENT_NAME_SIZE db 0 -cur_file_address: dw 0 ; Segment - dw 0 +cur_file_address: dw 0 + dw 0 ; Segment beg_file_address dw 0 end_file_address dw 0