;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; ;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ ;============================================================================== ;///// public functions /////////////////////////////////////////////////////// ;============================================================================== window.BORDER_SIZE = 5 macro FuncTable name, table_name, [label] { common align 4 \label name#.#table_name dword forward dd name#.#label common name#.sizeof.#table_name = $ - name#.#table_name } uglobal common_colours rd 32 draw_limits RECT endg align 4 ;------------------------------------------------------------------------------ syscall_draw_window: ;///// system function 0 ///////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ mov eax, edx shr eax, 24 and al, 0x0f cmp al, 5 jae .exit push eax inc [mouse_pause] call [_display.disable_mouse] call window._.sys_set_window call [_display.disable_mouse] pop eax or al, al jnz @f ; type I - original style call drawwindow_I jmp window._.draw_window_caption.2 @@: dec al jnz @f ; type II - only reserve area, no draw call sys_window_mouse dec [mouse_pause] call [draw_pointer] jmp .exit @@: dec al jnz @f ; type III - new style call drawwindow_III jmp window._.draw_window_caption.2 ; type IV & V - skinned window (resizable & not) @@: mov eax, [TASK_COUNT] movzx eax, word[WIN_POS + eax * 2] cmp eax, [CURRENT_TASK] setz al movzx eax, al push eax call drawwindow_IV jmp window._.draw_window_caption.2 .exit: ret align 4 ;------------------------------------------------------------------------------ syscall_display_settings: ;///// system function 48 /////////////////////////// ;------------------------------------------------------------------------------ ;; Redraw screen: ;< ebx = 0 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Set button style: ;< ebx = 1 ;< ecx = 0 (flat) or 1 (with gradient) ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Set system color palette: ;< ebx = 2 ;< ecx = pointer to color table ;< edx = size of color table ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Get system color palette: ;< ebx = 3 ;< ecx = pointer to color table buffer ;< edx = size of color table buffer ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Get skinned caption height: ;< ebx = 4 ;> eax = height in pixels ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Get screen working area: ;< ebx = 5 ;> eax = pack[16(left), 16(right)] ;> ebx = pack[16(top), 16(bottom)] ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Set screen working area: ;< ebx = 6 ;< ecx = pack[16(left), 16(right)] ;< edx = pack[16(top), 16(bottom)] ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Get skin margins: ;< ebx = 7 ;> eax = pack[16(left), 16(right)] ;> ebx = pack[16(top), 16(bottom)] ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Set skin: ;< ebx = 8 ;< ecx = pointer to FileInfoBlock struct ;> eax = FS error code ;------------------------------------------------------------------------------ cmp ebx, .sizeof.ftable / 4 ja @f jmp [.ftable + ebx * 4] @@: ret align 4 syscall_display_settings.00: xor eax, eax inc ebx cmp [windowtypechanged], ebx jne .exit mov [windowtypechanged], eax jmp syscall_display_settings._.redraw_whole_screen .exit: ret align 4 syscall_display_settings.01: and ecx, 1 cmp ecx, [buttontype] je .exit mov [buttontype], ecx mov [windowtypechanged], ebx .exit: ret align 4 syscall_display_settings.02: dec ebx mov esi, ecx and edx, 127 mov edi, common_colours mov ecx, edx rep movsb mov [windowtypechanged], ebx ret align 4 syscall_display_settings.03: mov edi, ecx and edx, 127 mov esi, common_colours mov ecx, edx rep movsb ret align 4 syscall_display_settings.04: mov eax, [_skinh] mov [esp + 32], eax ret align 4 syscall_display_settings.05: mov eax, [screen_workarea.left - 2] mov ax, word[screen_workarea.right] mov [esp + 32], eax mov eax, [screen_workarea.top - 2] mov ax, word[screen_workarea.bottom] mov [esp + 20], eax ret align 4 syscall_display_settings.06: xor esi, esi mov edi, [Screen_Max_X] mov eax, ecx movsx ebx, ax sar eax, 16 cmp eax, ebx jge .check_horizontal inc esi or eax, eax jge @f xor eax, eax @@: mov [screen_workarea.left], eax cmp ebx, edi jle @f mov ebx, edi @@: mov [screen_workarea.right], ebx .check_horizontal: mov edi, [Screen_Max_Y] mov eax, edx movsx ebx, ax sar eax, 16 cmp eax, ebx jge .check_if_redraw_needed inc esi or eax, eax jge @f xor eax, eax @@: mov [screen_workarea.top], eax cmp ebx, edi jle @f mov ebx, edi @@: mov [screen_workarea.bottom], ebx .check_if_redraw_needed: or esi, esi jz .exit call repos_windows jmp syscall_display_settings._.calculate_whole_screen .exit: ret align 4 syscall_display_settings.07: mov eax, [_skinmargins + 0] mov [esp + 32], eax mov eax, [_skinmargins + 4] mov [esp + 20], eax ret align 4 syscall_display_settings.08: mov ebx, ecx call read_skin_file mov [esp + 32], eax test eax, eax jnz .exit call syscall_display_settings._.calculate_whole_screen jmp syscall_display_settings._.redraw_whole_screen .exit: ret syscall_display_settings._.calculate_whole_screen: xor eax, eax xor ebx, ebx mov ecx, [Screen_Max_X] mov edx, [Screen_Max_Y] jmp calculatescreen syscall_display_settings._.redraw_whole_screen: xor eax, eax mov [draw_limits.left], eax mov [draw_limits.top], eax mov eax, [Screen_Max_X] mov [draw_limits.right], eax mov eax, [Screen_Max_Y] mov [draw_limits.bottom], eax mov eax, window_data jmp redrawscreen align 4 ;------------------------------------------------------------------------------ syscall_set_window_shape: ;///// system function 50 /////////////////////////// ;------------------------------------------------------------------------------ ;; Set window shape address: ;> ebx = 0 ;> ecx = shape data address ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Set window shape scale: ;> ebx = 1 ;> ecx = scale power (resulting scale is 2^ebx) ;------------------------------------------------------------------------------ mov edi, [current_slot] test ebx, ebx jne .shape_scale mov [edi + APPDATA.wnd_shape], ecx .shape_scale: dec ebx jnz .exit mov [edi + APPDATA.wnd_shape_scale], ecx .exit: ret align 4 ;------------------------------------------------------------------------------ syscall_move_window: ;///// system function 67 //////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ mov edi, [CURRENT_TASK] shl edi, 5 add edi, window_data test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED jnz .exit cmp ebx, -1 jne @f mov ebx, [edi + WDATA.box.left] @@: cmp ecx, -1 jne @f mov ecx, [edi + WDATA.box.top] @@: cmp edx, -1 jne @f mov edx, [edi + WDATA.box.width] @@: cmp esi, -1 jne @f mov esi, [edi + WDATA.box.height] @@: push esi edx ecx ebx mov eax, esp mov bl, [edi + WDATA.fl_wstate] call window._.set_window_box add esp, BOX.sizeof ; NOTE: do we really need this? to be reworked ; mov byte[DONT_DRAW_MOUSE], 0 ; mouse pointer ; mov byte[MOUSE_BACKGROUND], 0 ; no mouse under ; mov byte[MOUSE_DOWN], 0 ; react to mouse up/down ; NOTE: do we really need this? to be reworked ; call [draw_pointer] .exit: ret align 4 ;------------------------------------------------------------------------------ syscall_window_settings: ;///// system function 71 ///////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ dec ebx ; subfunction #1 - set window caption jnz .exit_fail ; NOTE: only window owner thread can set its caption, ; so there's no parameter for PID/TID mov edi, [CURRENT_TASK] shl edi, 5 mov [edi * 8 + SLOT_BASE + APPDATA.wnd_caption], ecx or [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION call window._.draw_window_caption xor eax, eax ; eax = 0 (success) ret ; .get_window_caption: ; dec eax ; subfunction #2 - get window caption ; jnz .exit_fail ; not implemented yet .exit_fail: xor eax, eax inc eax ; eax = 1 (fail) ret align 4 ;------------------------------------------------------------------------------ set_window_defaults: ;///////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ push eax ecx xor eax, eax mov ecx, WIN_STACK @@: inc eax add ecx, 2 ; process no mov [ecx + 0x000], ax ; positions in stack mov [ecx + 0x400], ax cmp ecx, WIN_POS - 2 jne @b pop ecx eax ret align 4 ;------------------------------------------------------------------------------ calculatescreen: ;///////////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? Scan all windows from bottom to top, calling `setscreen` for each one ;? intersecting given screen area ;------------------------------------------------------------------------------ ;> eax = left ;> ebx = top ;> ecx = right ;> edx = bottom ;------------------------------------------------------------------------------ push esi pushfd cli mov esi, 1 call window._.set_screen push ebp mov ebp, [TASK_COUNT] cmp ebp, 1 jbe .exit push edx ecx ebx eax .next_window: movzx edi, word[WIN_POS + esi * 2] shl edi, 5 cmp [CURRENT_TASK + edi + TASKDATA.state], TSTATE_FREE je .skip_window add edi, window_data test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED jnz .skip_window mov eax, [edi + WDATA.box.left] cmp eax, [esp + RECT.right] jg .skip_window mov ebx, [edi + WDATA.box.top] cmp ebx, [esp + RECT.bottom] jg .skip_window mov ecx, [edi + WDATA.box.width] add ecx, eax cmp ecx, [esp + RECT.left] jl .skip_window mov edx, [edi + WDATA.box.height] add edx, ebx cmp edx, [esp + RECT.top] jl .skip_window cmp eax, [esp + RECT.left] jae @f mov eax, [esp + RECT.left] @@: cmp ebx, [esp + RECT.top] jae @f mov ebx, [esp + RECT.top] @@: cmp ecx, [esp + RECT.right] jbe @f mov ecx, [esp + RECT.right] @@: cmp edx, [esp + RECT.bottom] jbe @f mov edx, [esp + RECT.bottom] @@: push esi movzx esi, word[WIN_POS + esi * 2] call window._.set_screen pop esi .skip_window: inc esi dec ebp jnz .next_window pop eax ebx ecx edx .exit: pop ebp popfd pop esi ret align 4 ;------------------------------------------------------------------------------ repos_windows: ;/////////////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ mov ecx, [TASK_COUNT] mov edi, window_data + WDATA.sizeof * 2 call force_redraw_background dec ecx jle .exit .next_window: mov [edi + WDATA.fl_redraw], 1 test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED jnz .fix_maximized mov eax, [edi + WDATA.box.left] add eax, [edi + WDATA.box.width] mov ebx, [Screen_Max_X] cmp eax, ebx jle .fix_vertical mov eax, [edi + WDATA.box.width] sub eax, ebx jle @f mov [edi + WDATA.box.width], ebx @@: sub ebx, [edi + WDATA.box.width] mov [edi + WDATA.box.left], ebx .fix_vertical: mov eax, [edi + WDATA.box.top] add eax, [edi + WDATA.box.height] mov ebx, [Screen_Max_Y] cmp eax, ebx jle .fix_client_box mov eax, [edi + WDATA.box.height] sub eax, ebx jle @f mov [edi + WDATA.box.height], ebx @@: sub ebx, [edi + WDATA.box.height] mov [edi + WDATA.box.top], ebx jmp .fix_client_box .fix_maximized: mov eax, [screen_workarea.left] mov [edi + WDATA.box.left], eax sub eax, [screen_workarea.right] neg eax mov [edi + WDATA.box.width], eax mov eax, [screen_workarea.top] mov [edi + WDATA.box.top], eax test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP jnz .fix_client_box sub eax, [screen_workarea.bottom] neg eax mov [edi + WDATA.box.height], eax .fix_client_box: call window._.set_window_clientbox add edi, WDATA.sizeof loop .next_window .exit: ret align 4 ;------------------------------------------------------------------------------ sys_window_mouse: ;//////////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ; NOTE: commented out since doesn't provide necessary functionality ; anyway, to be reworked ; push eax ; ; mov eax, [timer_ticks] ; cmp [new_window_starting], eax ; jb .exit ; ; mov byte[MOUSE_BACKGROUND], 0 ; mov byte[DONT_DRAW_MOUSE], 0 ; ; mov [new_window_starting], eax ; ; .exit: ; pop eax ret align 4 ;------------------------------------------------------------------------------ draw_rectangle: ;////////////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;> eax = pack[16(left), 16(right)] ;> ebx = pack[16(top), 16(bottom)] ;> esi = color ;------------------------------------------------------------------------------ push eax ebx ecx edi xor edi, edi .flags_set: push ebx ; set line color mov ecx, esi ; draw top border rol ebx, 16 push ebx rol ebx, 16 pop bx call [draw_line] ; draw bottom border mov ebx, [esp - 2] pop bx call [draw_line] pop ebx add ebx, 1 * 65536 - 1 ; draw left border rol eax, 16 push eax rol eax, 16 pop ax call [draw_line] ; draw right border mov eax, [esp - 2] pop ax call [draw_line] pop edi ecx ebx eax ret .forced: push eax ebx ecx edi xor edi, edi inc edi jmp .flags_set align 4 ;------------------------------------------------------------------------------ drawwindow_I_caption: ;//////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ push [edx + WDATA.cl_titlebar] mov esi, edx mov edx, [esi + WDATA.box.top] mov eax, edx lea ebx, [edx + 21] inc edx add eax, [esi + WDATA.box.height] cmp ebx, eax jbe @f mov ebx, eax @@: push ebx xor edi, edi .next_line: mov ebx, edx shl ebx, 16 add ebx, edx mov eax, [esi + WDATA.box.left] inc eax shl eax, 16 add eax, [esi + WDATA.box.left] add eax, [esi + WDATA.box.width] dec eax mov ecx, [esi + WDATA.cl_titlebar] test ecx, 0x80000000 jz @f sub ecx, 0x00040404 mov [esi + WDATA.cl_titlebar], ecx @@: and ecx, 0x00ffffff call [draw_line] inc edx cmp edx, [esp] jb .next_line add esp, 4 pop [esi + WDATA.cl_titlebar] ret align 4 ;------------------------------------------------------------------------------ drawwindow_I: ;//////////////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ pushad ; window border mov eax, [edx + WDATA.box.left - 2] mov ax, word[edx + WDATA.box.left] add ax, word[edx + WDATA.box.width] mov ebx, [edx + WDATA.box.top - 2] mov bx, word[edx + WDATA.box.top] add bx, word[edx + WDATA.box.height] mov esi, [edx + WDATA.cl_frames] call draw_rectangle ; window caption call drawwindow_I_caption ; window client area ; do we need to draw it? mov edi, [esi + WDATA.cl_workarea] test edi, 0x40000000 jnz .exit ; does client area have a positive size on screen? mov edx, [esi + WDATA.box.top] add edx, 21 + 5 mov ebx, [esi + WDATA.box.top] add ebx, [esi + WDATA.box.height] cmp edx, ebx jg .exit ; okay, let's draw it mov eax, 1 mov ebx, 21 mov ecx, [esi + WDATA.box.width] mov edx, [esi + WDATA.box.height] call [drawbar] .exit: popad ret align 4 ;------------------------------------------------------------------------------ drawwindow_III_caption: ;///////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ mov ecx, [edx + WDATA.cl_titlebar] push ecx mov esi, edx mov edx, [esi + WDATA.box.top] add edx, 4 mov ebx, [esi + WDATA.box.top] add ebx, 20 mov eax, [esi + WDATA.box.top] add eax, [esi + WDATA.box.height] cmp ebx, eax jb @f mov ebx, eax @@: push ebx xor edi, edi .next_line: mov ebx, edx shl ebx, 16 add ebx, edx mov eax, [esi + WDATA.box.left] shl eax, 16 add eax, [esi + WDATA.box.left] add eax, [esi + WDATA.box.width] add eax, 4 * 65536 - 4 mov ecx, [esi + WDATA.cl_titlebar] test ecx, 0x40000000 jz @f add ecx, 0x00040404 @@: test ecx, 0x80000000 jz @f sub ecx, 0x00040404 @@: mov [esi + WDATA.cl_titlebar], ecx and ecx, 0x00ffffff call [draw_line] inc edx cmp edx, [esp] jb .next_line add esp, 4 pop [esi + WDATA.cl_titlebar] ret align 4 ;------------------------------------------------------------------------------ drawwindow_III: ;////////////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ pushad ; window border mov eax, [edx + WDATA.box.left - 2] mov ax, word[edx + WDATA.box.left] add ax, word[edx + WDATA.box.width] mov ebx, [edx + WDATA.box.top - 2] mov bx, word[edx + WDATA.box.top] add bx, word[edx + WDATA.box.height] mov esi, [edx + WDATA.cl_frames] shr esi, 1 and esi, 0x007f7f7f call draw_rectangle push esi mov ecx, 3 mov esi, [edx + WDATA.cl_frames] .next_frame: add eax, 1 * 65536 - 1 add ebx, 1 * 65536 - 1 call draw_rectangle dec ecx jnz .next_frame pop esi add eax, 1 * 65536 - 1 add ebx, 1 * 65536 - 1 call draw_rectangle ; window caption call drawwindow_III_caption ; window client area ; do we need to draw it? mov edi, [esi + WDATA.cl_workarea] test edi, 0x40000000 jnz .exit ; does client area have a positive size on screen? mov edx, [esi + WDATA.box.top] add edx, 21 + 5 mov ebx, [esi + WDATA.box.top] add ebx, [esi + WDATA.box.height] cmp edx, ebx jg .exit ; okay, let's draw it mov eax, 5 mov ebx, 20 mov ecx, [esi + WDATA.box.width] mov edx, [esi + WDATA.box.height] sub ecx, 4 sub edx, 4 call [drawbar] .exit: popad ret align 4 ;------------------------------------------------------------------------------ waredraw: ;//////////////////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? Activate window, redrawing if necessary ;------------------------------------------------------------------------------ push -1 mov eax, [TASK_COUNT] lea eax, [WIN_POS + eax * 2] cmp eax, esi pop eax je .exit ; is it overlapped by another window now? push ecx call window._.check_window_draw test ecx, ecx pop ecx jz .do_not_draw ; yes it is, activate and update screen buffer mov byte[MOUSE_DOWN], 1 call window._.window_activate pushad mov edi, [TASK_COUNT] movzx esi, word[WIN_POS + edi * 2] shl esi, 5 add esi, window_data mov eax, [esi + WDATA.box.left] mov ebx, [esi + WDATA.box.top] mov ecx, [esi + WDATA.box.width] mov edx, [esi + WDATA.box.height] add ecx, eax add edx, ebx mov edi, [TASK_COUNT] movzx esi, word[WIN_POS + edi * 2] call window._.set_screen popad ; tell application to redraw itself mov [edi + WDATA.fl_redraw], 1 xor eax, eax jmp .exit .do_not_draw: ; no it's not, just activate the window call window._.window_activate xor eax, eax mov byte[MOUSE_BACKGROUND], al mov byte[DONT_DRAW_MOUSE], al .exit: mov byte[MOUSE_DOWN], 0 inc eax ret align 4 ;------------------------------------------------------------------------------ minimize_window: ;///////////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;> eax = window number on screen ;------------------------------------------------------------------------------ ;# corrupts [dl*] ;------------------------------------------------------------------------------ push edi pushfd cli ; is it already minimized? movzx edi, word[WIN_POS + eax * 2] shl edi, 5 add edi, window_data test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED jnz .exit push eax ebx ecx edx esi ; no it's not, let's do that or [edi + WDATA.fl_wstate], WSTATE_MINIMIZED mov eax, [edi + WDATA.box.left] mov [draw_limits.left], eax mov ecx, eax add ecx, [edi + WDATA.box.width] mov [draw_limits.right], ecx mov ebx, [edi + WDATA.box.top] mov [draw_limits.top], ebx mov edx, ebx add edx, [edi + WDATA.box.height] mov [draw_limits.bottom], edx call calculatescreen xor esi, esi xor eax, eax call redrawscreen pop esi edx ecx ebx eax .exit: popfd pop edi ret align 4 ;------------------------------------------------------------------------------ restore_minimized_window: ;//////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;> eax = window number on screen ;------------------------------------------------------------------------------ ;# corrupts [dl*] ;------------------------------------------------------------------------------ pushad pushfd cli ; is it already restored? movzx esi, word[WIN_POS + eax * 2] mov edi, esi shl edi, 5 add edi, window_data test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED jz .exit ; no it's not, let's do that mov [edi + WDATA.fl_redraw], 1 and [edi + WDATA.fl_wstate], not WSTATE_MINIMIZED mov ebp, window._.set_screen cmp eax, [TASK_COUNT] jz @f mov ebp, calculatescreen @@: mov eax, [edi + WDATA.box.left] mov ebx, [edi + WDATA.box.top] mov ecx, [edi + WDATA.box.width] mov edx, [edi + WDATA.box.height] add ecx, eax add edx, ebx call ebp mov byte[MOUSE_BACKGROUND], 0 .exit: popfd popad ret align 4 ; TODO: remove this proc ;------------------------------------------------------------------------------ window_check_events: ;///////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ; do we have window minimize/restore request? cmp [window_minimize], 0 je .exit ; okay, minimize or restore top-most window and exit mov eax, [TASK_COUNT] mov bl, 0 xchg [window_minimize], bl dec bl jnz @f call minimize_window jmp .exit @@: call restore_minimized_window .exit: ret align 4 ;------------------------------------------------------------------------------ sys_window_maximize_handler: ;///////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> esi = process slot ;------------------------------------------------------------------------------ mov edi, esi shl edi, 5 add edi, window_data ; can window change its height? ; only types 2 and 3 can be resized mov dl, [edi + WDATA.fl_wstyle] test dl, 2 jz .exit ; toggle normal/maximized window state mov bl, [edi + WDATA.fl_wstate] xor bl, WSTATE_MAXIMIZED ; calculate and set appropriate window bounds test bl, WSTATE_MAXIMIZED jz .restore_size mov eax, [screen_workarea.left] mov ecx, [screen_workarea.top] push [screen_workarea.bottom] \ [screen_workarea.right] \ ecx \ eax sub [esp + BOX.width], eax sub [esp + BOX.height], ecx mov eax, esp jmp .set_box .restore_size: mov eax, esi shl eax, 8 add eax, SLOT_BASE + APPDATA.saved_box push [eax + BOX.height] \ [eax + BOX.width] \ [eax + BOX.top] \ [eax + BOX.left] mov eax, esp .set_box: test bl, WSTATE_ROLLEDUP jz @f xchg eax, ecx call window._.get_rolledup_height mov [ecx + BOX.height], eax xchg eax, ecx @@: call window._.set_window_box add esp, BOX.sizeof .exit: ret align 4 ;------------------------------------------------------------------------------ sys_window_rollup_handler: ;/////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> esi = process slot ;------------------------------------------------------------------------------ mov edx, esi shl edx, 8 add edx, SLOT_BASE ; toggle normal/rolled up window state mov bl, [edi + WDATA.fl_wstate] xor bl, WSTATE_ROLLEDUP ; calculate and set appropriate window bounds test bl, WSTATE_ROLLEDUP jz .restore_size call window._.get_rolledup_height push eax \ [edi + WDATA.box.width] \ [edi + WDATA.box.top] \ [edi + WDATA.box.left] mov eax, esp jmp .set_box .restore_size: test bl, WSTATE_MAXIMIZED jnz @f add esp, -BOX.sizeof lea eax, [edx + APPDATA.saved_box] jmp .set_box @@: mov eax, [screen_workarea.top] push [screen_workarea.bottom] \ [edi + WDATA.box.width] \ eax \ [edi + WDATA.box.left] sub [esp + BOX.height], eax mov eax, esp .set_box: call window._.set_window_box add esp, BOX.sizeof ret align 4 ;------------------------------------------------------------------------------ sys_window_start_moving_handler: ;///////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> eax = old (original) window box ;> esi = process slot ;------------------------------------------------------------------------------ mov edi, eax call window._.draw_negative_box ret align 4 ;------------------------------------------------------------------------------ sys_window_end_moving_handler: ;/////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> eax = old (original) window box ;> ebx = new (final) window box ;> esi = process slot ;------------------------------------------------------------------------------ mov edi, ebx call window._.draw_negative_box mov edi, esi shl edi, 5 add edi, window_data mov eax, ebx mov bl, [edi + WDATA.fl_wstate] call window._.set_window_box ret align 4 ;------------------------------------------------------------------------------ sys_window_moving_handler: ;/////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> eax = old (from previous call) window box ;> ebx = new (current) window box ;> esi = process_slot ;------------------------------------------------------------------------------ mov edi, eax call window._.draw_negative_box mov edi, ebx call window._.draw_negative_box ret ;============================================================================== ;///// private functions ////////////////////////////////////////////////////// ;============================================================================== iglobal FuncTable syscall_display_settings, ftable, \ 00, 01, 02, 03, 04, 05, 06, 07, 08 align 4 window_topleft dd \ 1, 21, \ ;type 0 0, 0, \ ;type 1 5, 20, \ ;type 2 5, ?, \ ;type 3 {set by skin} 5, ? ;type 4 {set by skin} endg ;uglobal ; NOTE: commented out since doesn't provide necessary functionality anyway, ; to be reworked ; new_window_starting dd ? ;endg align 4 ;------------------------------------------------------------------------------ window._.invalidate_screen: ;////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> eax = old (original) window box ;> ebx = new (final) window box ;> edi = pointer to WDATA struct ;------------------------------------------------------------------------------ push eax ebx ; TODO: do we really need `draw_limits`? mov ecx, [eax + BOX.left] mov edx, [ebx + BOX.left] cmp ecx, edx jle @f xchg ecx, edx @@: mov [draw_limits.left], ecx mov ecx, [eax + BOX.width] cmp ecx, [ebx + BOX.width] jae @f mov ecx, [ebx + BOX.width] @@: add ecx, edx mov [draw_limits.right], ecx mov ecx, [eax + BOX.top] mov edx, [ebx + BOX.top] cmp ecx, edx jle @f xchg ecx, edx @@: mov [draw_limits.top], ecx mov ecx, [eax + BOX.height] cmp ecx, [ebx + BOX.height] jae @f mov ecx, [ebx + BOX.height] @@: add ecx, edx mov [draw_limits.bottom], ecx ; recalculate screen buffer at old position push ebx mov edx, [eax + BOX.height] mov ecx, [eax + BOX.width] mov ebx, [eax + BOX.top] mov eax, [eax + BOX.left] add ecx, eax add edx, ebx call calculatescreen pop eax ; recalculate screen buffer at new position mov edx, [eax + BOX.height] mov ecx, [eax + BOX.width] mov ebx, [eax + BOX.top] mov eax, [eax + BOX.left] add ecx, eax add edx, ebx call calculatescreen mov eax, edi call redrawscreen ; tell window to redraw itself mov [edi + WDATA.fl_redraw], 1 pop ebx eax ret align 4 ;------------------------------------------------------------------------------ window._.set_window_box: ;///////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> eax = pointer to BOX struct ;> bl = new window state flags ;> edi = pointer to WDATA struct ;------------------------------------------------------------------------------ push eax ebx esi ; don't do anything if the new box is identical to the old cmp bl, [edi + WDATA.fl_wstate] jnz @f mov esi, eax push edi if WDATA.box add edi, WDATA.box end if mov ecx, 4 repz cmpsd pop edi jz .exit @@: add esp, -BOX.sizeof mov ebx, esp if WDATA.box lea esi, [edi + WDATA.box] else mov esi, edi ; optimization for WDATA.box = 0 end if xchg eax, esi mov ecx, BOX.sizeof call memmove xchg eax, esi xchg ebx, esi call memmove mov eax, ebx mov ebx, esi call window._.check_window_position call window._.set_window_clientbox call window._.invalidate_screen add esp, BOX.sizeof mov cl, [esp + 4] mov ch, cl xchg cl, [edi + WDATA.fl_wstate] or cl, ch test cl, WSTATE_MAXIMIZED jnz .exit mov eax, edi sub eax, window_data shl eax, 3 add eax, SLOT_BASE lea ebx, [edi + WDATA.box] xchg esp, ebx pop [eax + APPDATA.saved_box.left] \ [eax + APPDATA.saved_box.top] \ [eax + APPDATA.saved_box.width] \ edx xchg esp, ebx test ch, WSTATE_ROLLEDUP jnz .exit mov [eax + APPDATA.saved_box.height], edx .exit: pop esi ebx eax ret align 4 ;------------------------------------------------------------------------------ window._.set_window_clientbox: ;/////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> edi = pointer to WDATA struct ;------------------------------------------------------------------------------ push eax ecx edi mov eax, [_skinh] mov [window_topleft + 8 * 3 + 4], eax mov [window_topleft + 8 * 4 + 4], eax mov ecx, edi sub edi, window_data shl edi, 3 test [ecx + WDATA.fl_wstyle], WSTYLE_CLIENTRELATIVE jz .whole_window movzx eax, [ecx + WDATA.fl_wstyle] and eax, 0x0F mov eax, [eax * 8 + window_topleft + 0] mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.left], eax shl eax, 1 neg eax add eax, [ecx + WDATA.box.width] mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.width], eax movzx eax, [ecx + WDATA.fl_wstyle] and eax, 0x0F push [eax * 8 + window_topleft + 0] mov eax, [eax * 8 + window_topleft + 4] mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.top], eax neg eax sub eax, [esp] add eax, [ecx + WDATA.box.height] mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.height], eax add esp, 4 jmp .exit .whole_window: xor eax, eax mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.left], eax mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.top], eax mov eax, [ecx + WDATA.box.width] mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.width], eax mov eax, [ecx + WDATA.box.height] mov [edi + SLOT_BASE + APPDATA.wnd_clientbox.height], eax .exit: pop edi ecx eax ret align 4 ;------------------------------------------------------------------------------ window._.sys_set_window: ;///////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;< edx = pointer to WDATA struct ;------------------------------------------------------------------------------ mov eax, [CURRENT_TASK] shl eax, 5 add eax, window_data ; save window colors mov [eax + WDATA.cl_workarea], edx mov [eax + WDATA.cl_titlebar], esi mov [eax + WDATA.cl_frames], edi mov edi, eax ; was it already defined before? test [edi + WDATA.fl_wdrawn], 1 jnz .set_client_box ; NOTE: commented out since doesn't provide necessary functionality ; anyway, to be reworked ; mov eax, [timer_ticks] ; [0xfdf0] ; add eax, 100 ; mov [new_window_starting], eax ; no it wasn't, performing initial window definition movzx eax, bx mov [edi + WDATA.box.width], eax movzx eax, cx mov [edi + WDATA.box.height], eax sar ebx, 16 sar ecx, 16 mov [edi + WDATA.box.left], ebx mov [edi + WDATA.box.top], ecx call window._.check_window_position push ecx edi mov cl, [edi + WDATA.fl_wstyle] mov eax, [edi + WDATA.cl_frames] sub edi, window_data shl edi, 3 add edi, SLOT_BASE and cl, 0x0F cmp cl, 3 je @f cmp cl, 4 je @f xor eax, eax @@: mov [edi + APPDATA.wnd_caption], eax mov esi, [esp] add edi, APPDATA.saved_box movsd movsd movsd movsd pop edi ecx mov esi, [CURRENT_TASK] movzx esi, word[WIN_STACK + esi * 2] lea esi, [WIN_POS + esi * 2] call waredraw mov eax, [edi + WDATA.box.left] mov ebx, [edi + WDATA.box.top] mov ecx, [edi + WDATA.box.width] mov edx, [edi + WDATA.box.height] add ecx, eax add edx, ebx call calculatescreen mov byte[KEY_COUNT], 0 ; empty keyboard buffer mov byte[BTN_COUNT], 0 ; empty button buffer .set_client_box: ; update window client box coordinates call window._.set_window_clientbox ; reset window redraw flag and exit mov [edi + WDATA.fl_redraw], 0 mov edx, edi ret align 4 ;------------------------------------------------------------------------------ window._.check_window_position: ;////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? Check if window is inside screen area ;------------------------------------------------------------------------------ ;> edi = pointer to WDATA ;------------------------------------------------------------------------------ push eax ebx ecx edx esi mov eax, [edi + WDATA.box.left] mov ebx, [edi + WDATA.box.top] mov ecx, [edi + WDATA.box.width] mov edx, [edi + WDATA.box.height] mov esi, [Screen_Max_X] cmp ecx, esi ja .fix_width_high .check_left: or eax, eax jl .fix_left_low add eax, ecx cmp eax, esi jg .fix_left_high .check_height: mov esi, [Screen_Max_Y] cmp edx, esi ja .fix_height_high .check_top: or ebx, ebx jl .fix_top_low add ebx, edx cmp ebx, esi jg .fix_top_high .exit: pop esi edx ecx ebx eax ret .fix_width_high: mov ecx, esi mov [edi + WDATA.box.width], esi jmp .check_left .fix_left_low: xor eax, eax mov [edi + WDATA.box.left], eax jmp .check_height .fix_left_high: mov eax, esi sub eax, ecx mov [edi + WDATA.box.left], eax jmp .check_height .fix_height_high: mov edx, esi mov [edi + WDATA.box.height], esi jmp .check_top .fix_top_low: xor ebx, ebx mov [edi + WDATA.box.top], ebx jmp .exit .fix_top_high: mov ebx, esi sub ebx, edx mov [edi + WDATA.box.top], ebx jmp .exit align 4 ;------------------------------------------------------------------------------ window._.get_titlebar_height: ;//////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> edi = pointer to WDATA ;------------------------------------------------------------------------------ mov al, [edi + WDATA.fl_wstyle] and al, 0x0f cmp al, 0x03 jne @f mov eax, [_skinh] ret @@: mov eax, 21 ret align 4 ;------------------------------------------------------------------------------ window._.get_rolledup_height: ;//////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ ;> edi = pointer to WDATA ;------------------------------------------------------------------------------ mov al, [edi + WDATA.fl_wstyle] and al, 0x0f cmp al, 0x03 jb @f mov eax, [_skinh] add eax, 3 ret @@: or al, al jnz @f mov eax, 21 ret @@: mov eax, 21 + 2 ret align 4 ;------------------------------------------------------------------------------ window._.set_screen: ;///////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? Reserve window area in screen buffer ;------------------------------------------------------------------------------ ;> eax = left ;> ebx = top ;> ecx = right ;> edx = bottom ;> esi = process number ;------------------------------------------------------------------------------ virtual at esp ff_x dd ? ff_y dd ? ff_width dd ? ff_xsz dd ? ff_ysz dd ? ff_scale dd ? end virtual pushad cmp esi, 1 jz .check_for_shaped_window mov edi, esi shl edi, 5 cmp [window_data + edi + WDATA.box.width], 0 jnz .check_for_shaped_window cmp [window_data + edi + WDATA.box.height], 0 jz .exit .check_for_shaped_window: mov edi, esi shl edi, 8 add edi, SLOT_BASE cmp [edi + APPDATA.wnd_shape], 0 jne .shaped_window ; get x&y size sub ecx, eax sub edx, ebx inc ecx inc edx ; get WinMap start push esi mov edi, [Screen_Max_X] inc edi mov esi, edi imul edi, ebx add edi, eax add edi, [_WinMapAddress] pop eax mov ah, al push ax shl eax, 16 pop ax .next_line: push ecx shr ecx, 2 rep stosd mov ecx, [esp] and ecx, 3 rep stosb pop ecx add edi, esi sub edi, ecx dec edx jnz .next_line jmp .exit .shaped_window: ; for (y=0; y <= x_size; y++) ; for (x=0; x <= x_size; x++) ; if (shape[coord(x,y,scale)]==1) ; set_pixel(x, y, process_number); sub ecx, eax sub edx, ebx inc ecx inc edx push [edi + APPDATA.wnd_shape_scale] ; push scale first -> for loop ; get WinMap start -> ebp push eax mov eax, [Screen_Max_X] ; screen_sx inc eax imul eax, ebx add eax, [esp] add eax, [_WinMapAddress] mov ebp, eax mov edi, [edi + APPDATA.wnd_shape] pop eax ; eax = x_start ; ebx = y_start ; ecx = x_size ; edx = y_size ; esi = process_number ; edi = &shape ; [scale] push edx ecx ; for loop - x,y size mov ecx, esi shl ecx, 5 mov edx, [window_data + ecx + WDATA.box.top] push [window_data + ecx + WDATA.box.width] ; for loop - width mov ecx, [window_data + ecx + WDATA.box.left] sub ebx, edx sub eax, ecx push ebx eax ; for loop - x,y add [ff_xsz], eax add [ff_ysz], ebx mov ebx, [ff_y] .ff_new_y: mov edx, [ff_x] .ff_new_x: ; -- body -- mov ecx, [ff_scale] mov eax, [ff_width] inc eax shr eax, cl push ebx edx shr ebx, cl shr edx, cl imul eax, ebx add eax, edx pop edx ebx add eax, edi call .read_byte test al,al jz @f mov eax, esi mov [ebp], al ; -- end body -- @@: inc ebp inc edx cmp edx, [ff_xsz] jb .ff_new_x sub ebp, [ff_xsz] add ebp, [ff_x] add ebp, [Screen_Max_X] ; screen.x inc ebp inc ebx cmp ebx, [ff_ysz] jb .ff_new_y add esp, 24 .exit: popad ret .read_byte: ; eax - address ; esi - slot push eax ecx edx esi xchg eax, esi lea ecx, [esp + 12] mov edx, 1 call read_process_memory pop esi edx ecx eax ret align 4 ;------------------------------------------------------------------------------ window._.window_activate: ;//////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? Activate window ;------------------------------------------------------------------------------ ;> esi = pointer to WIN_POS+ window data ;------------------------------------------------------------------------------ push eax ebx ; if type of current active window is 3 or 4, it must be redrawn mov ebx, [TASK_COUNT] movzx ebx, word[WIN_POS + ebx * 2] shl ebx, 5 add eax, window_data mov al, [window_data + ebx + WDATA.fl_wstyle] and al, 0x0f cmp al, 0x03 je .set_window_redraw_flag cmp al, 0x04 jne .move_others_down .set_window_redraw_flag: mov [window_data + ebx + WDATA.fl_redraw], 1 .move_others_down: ; ax <- process no movzx ebx, word[esi] ; ax <- position in window stack movzx ebx, word[WIN_STACK + ebx * 2] ; drop others xor eax, eax .next_stack_window: cmp eax, [TASK_COUNT] jae .move_self_up inc eax cmp [WIN_STACK + eax * 2], bx jbe .next_stack_window dec word[WIN_STACK + eax * 2] jmp .next_stack_window .move_self_up: movzx ebx, word[esi] ; number of processes mov ax, [TASK_COUNT] ; this is the last (and the upper) mov [WIN_STACK + ebx * 2], ax ; update on screen - window stack xor eax, eax .next_window_pos: cmp eax, [TASK_COUNT] jae .reset_vars inc eax movzx ebx, word[WIN_STACK + eax * 2] mov [WIN_POS + ebx * 2], ax jmp .next_window_pos .reset_vars: mov byte[KEY_COUNT], 0 mov byte[BTN_COUNT], 0 mov word[MOUSE_SCROLL_H], 0 mov word[MOUSE_SCROLL_V], 0 pop ebx eax ret align 4 ;------------------------------------------------------------------------------ window._.check_window_draw: ;////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? Check if window is necessary to draw ;------------------------------------------------------------------------------ ;> edi = pointer to WDATA ;------------------------------------------------------------------------------ mov cl, [edi + WDATA.fl_wstyle] and cl, 0x0f cmp cl, 3 je .exit.redraw ; window type 3 cmp cl, 4 je .exit.redraw ; window type 4 push eax ebx edx esi mov eax, edi sub eax, window_data shr eax, 5 movzx eax, word[WIN_STACK + eax * 2] ; get value of the curr process lea esi, [WIN_POS + eax * 2] ; get address of this process at 0xC400 .next_window: add esi, 2 mov eax, [TASK_COUNT] lea eax, word[WIN_POS + eax * 2] ; number of the upper window cmp esi, eax ja .exit.no_redraw movzx edx, word[esi] shl edx, 5 cmp [CURRENT_TASK + edx + TASKDATA.state], TSTATE_FREE je .next_window mov eax, [edi + WDATA.box.top] mov ebx, [edi + WDATA.box.height] add ebx, eax mov ecx, [window_data + edx + WDATA.box.top] cmp ecx, ebx jge .next_window add ecx, [window_data + edx + WDATA.box.height] cmp eax, ecx jge .next_window mov eax, [edi + WDATA.box.left] mov ebx, [edi + WDATA.box.width] add ebx, eax mov ecx, [window_data + edx + WDATA.box.left] cmp ecx, ebx jge .next_window add ecx, [window_data + edx + WDATA.box.width] cmp eax, ecx jge .next_window pop esi edx ebx eax .exit.redraw: xor ecx, ecx inc ecx ret .exit.no_redraw: pop esi edx ebx eax xor ecx, ecx ret align 4 ;------------------------------------------------------------------------------ window._.draw_window_caption: ;//////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? ;------------------------------------------------------------------------------ inc [mouse_pause] call [_display.disable_mouse] xor eax, eax mov edx, [TASK_COUNT] movzx edx, word[WIN_POS + edx * 2] cmp edx, [CURRENT_TASK] jne @f inc eax @@: mov edx, [CURRENT_TASK] shl edx, 5 add edx, window_data movzx ebx, [edx + WDATA.fl_wstyle] and bl, 0x0F cmp bl, 3 je .draw_caption_style_3 cmp bl, 4 je .draw_caption_style_3 jmp .not_style_3 .draw_caption_style_3: push edx call drawwindow_IV_caption add esp, 4 jmp .2 .not_style_3: cmp bl, 2 jne .not_style_2 call drawwindow_III_caption jmp .2 .not_style_2: cmp bl, 0 jne .2 call drawwindow_I_caption .2: mov edi, [CURRENT_TASK] shl edi, 5 test [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION jz .exit mov edx, [edi * 8 + SLOT_BASE + APPDATA.wnd_caption] or edx, edx jz .exit movzx eax, [edi + window_data + WDATA.fl_wstyle] and al, 0x0F cmp al, 3 je .skinned cmp al, 4 je .skinned jmp .not_skinned .skinned: mov ebp, [edi + window_data + WDATA.box.left - 2] mov bp, word[edi + window_data + WDATA.box.top] movzx eax, word[edi + window_data + WDATA.box.width] sub ax, [_skinmargins.left] sub ax, [_skinmargins.right] push edx cwde cdq mov ebx, 6 idiv ebx pop edx or eax, eax js .exit mov esi, eax mov ebx, dword[_skinmargins.left - 2] mov bx, word[_skinh] sub bx, [_skinmargins.bottom] sub bx, [_skinmargins.top] sar bx, 1 adc bx, 0 add bx, [_skinmargins.top] add bx, -3 add ebx, ebp jmp .dodraw .not_skinned: cmp al, 1 je .exit mov ebp, [edi + window_data + WDATA.box.left - 2] mov bp, word[edi + window_data + WDATA.box.top] movzx eax, word[edi + window_data + WDATA.box.width] sub eax, 16 push edx cwde cdq mov ebx, 6 idiv ebx pop edx or eax, eax js .exit mov esi, eax mov ebx, 0x00080007 add ebx, ebp .dodraw: mov ecx, [common_colours + 16] or ecx, 0x80000000 xor edi, edi call dtext_asciiz_esi .exit: dec [mouse_pause] call [draw_pointer] ret align 4 ;------------------------------------------------------------------------------ window._.draw_negative_box: ;////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? Draw negative box ;------------------------------------------------------------------------------ ;> edi = pointer to BOX struct ;------------------------------------------------------------------------------ push eax ebx esi mov eax, [edi + BOX.left - 2] mov ax, word[edi + BOX.left] add ax, word[edi + BOX.width] mov ebx, [edi + BOX.top - 2] mov bx, word[edi + BOX.top] add bx, word[edi + BOX.height] mov esi, 0x01000000 call draw_rectangle.forced pop esi ebx eax ret