%include "ponydos.inc" struc window .next resw 1 .width resw 1 .height resw 1 .x resw 1 .y resw 1 .data resw 1 .size: endstruc cpu 8086 bits 16 org 0 ; 0x0000 jmp near process_event ; 0x0003 initialize: push ds push cs pop ds ; Set wallpaper mov si, wallpaper_name xor dx, dx call PONYDOS_SEG:SYS_OPEN_FILE mov bp, PONYDOS_SEG mov es, bp mov bx, GLOBAL_WALLPAPER xor di, di ; read call PONYDOS_SEG:SYS_MODIFY_SECTORS ; Create window 1 mov ax, cs add ax, 0x000 xchg [es:GLOBAL_WINDOW_CHAIN_HEAD], ax mov [windows + 0*window.size + window.next], ax mov word [windows + 0*window.size + window.width], 16 mov word [windows + 0*window.size + window.height], 4 mov word [windows + 0*window.size + window.x], 10 mov word [windows + 0*window.size + window.y], 3 mov word [windows + 0*window.size + window.data], window_1 ; Create window 2 mov ax, cs add ax, 0x001 xchg [es:GLOBAL_WINDOW_CHAIN_HEAD], ax mov [windows + 1*window.size + window.next], ax mov word [windows + 1*window.size + window.width], 40 mov word [windows + 1*window.size + window.height], 4 mov word [windows + 1*window.size + window.x], 14 mov word [windows + 1*window.size + window.y], 6 mov word [windows + 1*window.size + window.data], window_2 call request_redraw ; Temporary testing mov ax, cs mov es, ax mov di, window_1 + 32 mov cx, 3 mov dx, 16 call print_ls mov di, window_2 + 80 mov cx, 3 mov dx, 40 call print_ls pop ds retf process_event: push bx push cx push dx push si push di push bp push ds push es mov bp, cs mov ds, bp mov es, bp cmp al, WM_PAINT jne .not_paint call paint jmp .end .not_paint: cmp al, WM_MOUSE jne .not_mouse call mouse jmp .end .not_mouse: cmp al, WM_KEYBOARD jne .not_keyboard call keyboard jmp .end .not_keyboard: cmp al, WM_UNHOOK jne .not_remove call unhook .not_remove: .end: pop es pop ds pop bp pop di pop si pop dx pop cx pop bx retf paint: call get_window mov bx, [si + window.next] call forward_event ; Draw a rectangle on-screen mov bx, [si + window.width] mov cx, bx mov dx, [si + window.height] mov di, [si + window.x] mov bp, [si + window.y] mov si, [si + window.data] call PONYDOS_SEG:SYS_DRAW_RECT ret mouse: call get_window push cx push bx ; Y xor bx, bx mov bl, ch ; X xor ch, ch cmp cx, [si + window.x] jl .outside cmp bx, [si + window.y] jl .outside sub cx, [si + window.x] cmp [si + window.width], cx jle .outside sub bx, [si + window.y] cmp [si + window.height], bx jle .outside pop bx mov si, [si + window.data] add si, 18 test dl, MOUSE_PRIMARY jz .not_clicking .clicking: call raise_window mov al, '*' xchg byte [si], al cmp al, '*' je .end call request_redraw jmp .end .not_clicking: mov al, ' ' xchg byte [si], al cmp al, ' ' je .end call request_redraw .end: pop cx ret .outside: pop bx pop cx mov bx, [si + window.next] call forward_event ret keyboard: call get_window mov si, [si + window.data] add si, 20 mov [si], cl call request_redraw ret unhook: call get_window cmp bx, cx je .match push bx ; Forward the event mov bx, [si + window.next] call forward_event ; Update next ID ; If window.next was zero, forward_event will also return zero so ; this is safe in all cases mov [si + window.next], ax ; Return own ID to keep self in the chain pop ax ret .match: ; Return next ID in the chain to unhook mov ax, [si + window.next] ret ; in: ; bx = valid window id for this process ; out: ; si = pointer to window's data block get_window: push bx mov si, cs sub bx, si mov si, windows push ax push dx mov ax, window.size mul bx add si, ax pop dx pop ax pop bx ret request_redraw: push es push bp mov bp, PONYDOS_SEG mov es, bp mov byte [es:GLOBAL_REDRAW], 1 pop bp pop es ret ; in: ; cx = window ID to unhook unhook_window: push ax push bx push es mov bx, PONYDOS_SEG mov es, bx mov bx, [es:GLOBAL_WINDOW_CHAIN_HEAD] mov al, WM_UNHOOK call forward_event mov [es:GLOBAL_WINDOW_CHAIN_HEAD], ax pop es pop bx pop ax ret ; in: ; bx = window ID to raise raise_window: push cx push si push es call get_window mov cx, bx call unhook_window mov cx, PONYDOS_SEG mov es, cx mov cx, bx xchg [es:GLOBAL_WINDOW_CHAIN_HEAD], cx mov [si + window.next], cx pop es pop si pop cx ret ; in ; cx = height of window (>= 1) ; dx = width of window in characters ; es:di = start of output print_ls: push ax push bx push cx push si push di push bp push ds mov bp, PONYDOS_SEG mov ds, bp push cx push di mov si, GLOBAL_DIRENTS + 2 xor ax, ax ; Maximum filename size .name_loop: cmp word [ds:si - 2], 0 je .done_names push cx call strlen mov bx, cx pop cx cmp bx, dx jle .not_long_filename mov bx, dx .not_long_filename: cmp ax, bx jge .not_new_max mov ax, bx .not_new_max: push si push di .copy: movsb inc di ; Formatting dec bx jnz .copy pop di pop si ; Move to next line add di, dx add di, dx add si, FS_DIRENT_SIZE cmp si, GLOBAL_DIRENTS + 0x200 jge .done_names dec cx jnz .name_loop .done_names: pop di pop cx ; Don't print sizes for too short a window cmp dx, 10 jle .done add ax, 5 ; 1 whitespace, 4 length cmp ax, dx jle .not_truncate mov ax, dx .not_truncate: sub ax, 5 ; Go to start of where to put the file length add di, ax add di, ax mov si, GLOBAL_DIRENTS .size_loop: mov ax, word [ds:si] test ax, ax jz .done mov byte [es:di + 8], 'K' shr ax, 1 aam ; mango add ax, 0x3030 cmp ah, 0x30 je .one_digit mov byte [es:di + 2], ' ' mov [es:di + 4], ah jmp .one_digit_print .one_digit: test word [ds:si], 1 jnz .one_and_half_digit mov byte [es:di + 4], ' ' .one_digit_print: mov [es:di + 6], al jmp .next_iter_size_loop .one_and_half_digit: mov byte [es:di], ' ' mov byte [es:di + 2], al mov byte [es:di + 4], '.' mov byte [es:di + 6], '5' .next_iter_size_loop: ; Move to next line add di, dx add di, dx add si, FS_DIRENT_SIZE cmp si, GLOBAL_DIRENTS + 0x200 jge .done dec cx jnz .size_loop .done: pop ds pop bp pop di pop si pop cx pop bx pop ax ret ; in: ; ds:si = string ; out: ; cx = stlen strlen: push ax push di push es mov cx, ds mov es, cx mov di, si mov cx, -1 xor ax, ax repne scasb not cx dec cx pop es pop di pop ax ret ; in: ; bx = window ID ; out: ; ax = return value of event handler; 0 if window ID is 0 forward_event: push bp cmp bx, 0 je .id_is_zero push cs ; Return segment mov bp, .end push bp ; Return offset mov bp, 0xf000 and bp, bx push bp ; Call segment xor bp, bp push bp ; Call offset retf .id_is_zero: ; This gets skipped over in normal execution, because it ; explicitly returns to .end xor ax, ax .end: pop bp ret wallpaper_name db 'ponydos.wall', 0 %include "debug.inc" window_1: db 'W', 0x0f, 'i', 0x0f, 'n', 0x0f, 'd', 0x0f, 'o', 0x0f, 'w', 0x0f, ' ', 0x0f, '1', 0x0f times 8 db ' ', 0x0f times 16 db ' ', 0xf0 times 16 db ' ', 0xf0 times 16 db ' ', 0xf0 window_2: db 'W', 0x0f, 'i', 0x0f, 'n', 0x0f, 'd', 0x0f, 'o', 0x0f, 'w', 0x0f, ' ', 0x0f, '2', 0x0f times 32 db ' ', 0x0f times 40 db ' ', 0xf0 times 40 db ' ', 0xf0 times 40 db ' ', 0xf0 windows: times window.size db 0 times window.size db 0