kolibrios-fun/programs/system/calendar/trunk/calendar.asm
Ivan Baravy 49fa7c89bf calendar: Fix week day calculation (resolve #127).
Note: qemu-system-i386 ... -rtc base="2020-02-02T23:59:45"

git-svn-id: svn://kolibrios.org@7724 a494cfbc-eb01-0410-851d-a64ba20cac60
2020-02-19 23:15:56 +00:00

867 lines
14 KiB
NASM

; Calendar for KolibriOS
;
; v1.5 - time redesign by Heavyiron
; v1.2 - v1.55 - new design and functionality by Leency
; v1.1 - add change time support by DedOK
; v1.0 - written in pure assembler by Ivushkin Andrey aka Willow
; also - diamond, spraid, fedesco
;
; Created: November 1, 2004
use32
org 0x0
db 'MENUET01'
dd 0x01
dd START
dd I_END
dd 0x1000
dd 0x1000
dd 0x0
dd 0x0
include '..\..\..\macros.inc'
include 'lang.inc'
include 'data.inc'
macro ShowFocus field,reg
{
local .nofocus, .exit
cmp [focus],field
jne .nofocus
if reg eq
mov ecx,COL_ACTIVE_TEXT
else
mov reg,COL_ACTIVE_TEXT
end if
jmp .exit
.nofocus:
if reg eq
mov ecx,COL_DROPDOWN_T
else
mov reg,COL_DROPDOWN_T
end if
.exit:
}
macro GetSkinHeight
{
mov eax,48
mov ebx,4
int 0x40
}
macro DrawRect color1,color2,color3,color4 ; pizdec... but optimized well
{
; top border-outer
push ebx
push ecx
mov eax,13
mov bx,DATE_BUTTON_WIDTH
mov edx,color1
mov cx,1
mcall
; left border-outer
mov bx,1
mov cx,DATE_BUTTON_HEIGHT
mcall
; top border-inner
mov edx,color2
add ebx,1 shl 16
add ecx,1 shl 16
mov bx,DATE_BUTTON_WIDTH-1
mov cx,1
; left border-inner
mcall
mov bx,1
mov cx,DATE_BUTTON_HEIGHT-2
mcall
; inner
mov edx,color3
add ebx,1 shl 16
add ecx,1 shl 16
mov bx,DATE_BUTTON_WIDTH-4
mov cx,DATE_BUTTON_HEIGHT-3
mcall
; bottom border-inner
mov edx,color4
add ebx,DATE_BUTTON_WIDTH shl 16
sub ebx,4 shl 16
mov bx,1
mov cx,DATE_BUTTON_HEIGHT-3
mcall
; right border-outer
mov edx,color2
add ebx,1 shl 16
sub ecx,1 shl 16
add cx,1
mcall
; right border-outer 2
mov edx,color1
add ebx,1 shl 16
sub ecx,1 shl 16
add cx,2
add cx,1
mcall
; bottom border-outer
mov edx,color2
pop ecx
pop ebx
add ecx,DATE_BUTTON_HEIGHT shl 16
sub ecx,1 shl 16
add ebx,1 shl 16
mov cx,1
mcall
; bottom border-outer 2
mov edx,color1
add ecx,1 shl 16
mcall
add ebx,1 shl 16
sub ecx,1 shl 16
; left border-outer
mov edx,color4
add ebx,1 shl 16
sub ecx,1 shl 16
sub bx,2
mcall
}
str2int:
xor eax,eax
lodsb
mov ebx,eax
shr ebx,4
and eax,0xf
imul ebx,10
add al,bl
ret
get_current_date:
mcall 29
mov [datestr],eax
mov esi,datestr
call str2int
add eax,1900
mov [curYear],eax
call str2int
dec eax
mov [curMonth],eax
call str2int
mov [curDay],eax
test byte[esi],0
jnz .no2000
add [curYear],100
.no2000:
ret
check_midnight:
mov ebx,[datestr]
mcall 29
cmp eax,ebx
je end_check_midnight
call get_current_date
call draw_days
end_check_midnight:
ret
;===============================================================
START:
call get_current_date
m2m [Year], [curYear]
m2m [Month], [curMonth]
m2m [day_sel], [curDay]
call calculate
red:
call define_window
still:
mcall 23,50 ; wait here for event
.evt:
mov ebp,[focus]
cmp eax,1
je red
cmp eax,2
je key
cmp eax,3
je button
call check_midnight
call draw_clock
jmp still
key:
mcall 2 ; get pressed key
cmp ah,9
jne no_tab
.tab:
cmp ebp,FOCUSABLE
JAE foc_cycle
inc [focus]
upd:
call calculate
jmp red
foc_cycle:
mov [focus],2
jmp upd
no_tab:
push eax
shr eax,8
mov ecx,12
mov edi,Fkeys
repne scasb
pop eax
jnz .noFkey
sub edi,Fkeys+1
mov [Month],edi
jmp upd
.noFkey:
cmp ebp,2
jne .nomonth
cmp ah,177
je noclose.drop
jmp still
.nomonth:
cmp ebp,3
je noy_up.year_evt
cmp ebp,4
jne still
mov ebx,[day_sel]
cmp ah,176 ; left arrow
jg still
cmp ah,179
jl still
shr eax,8
sub eax,176
movsx ecx,byte[day_bounds+eax*2]
movzx eax,byte[day_bounds+eax*2+1]
add ecx,ebx
test eax,eax
jz .chk0
cmp ecx,eax
ja still
.ok:
mov [day_sel],ecx
call draw_days
jmp still
.chk0:
cmp ecx,eax
jle still
jmp .ok
day_bounds db -1,0,7,0,-7,0,1,0 ; left,down,up,right
button:
mcall 17
movzx ebx,ah
cmp ah,200
jbe nodayselect
sub ah,200
mov byte[day_sel],ah
cmp ebp,5
jne .redraw
call draw_days
jmp still
.redraw:
mov [focus],4
jmp red
nodayselect:
cmp ah,100
jb no_list
sub ah,100
mov byte[Month],ah
mov [focus],2
jmp upd
no_list:
cmp ah,1
jne noclose
close:
mcall -1 ; clore programm
noclose:
cmp ah,72
je plus_he
cmp ah,73
je plus_hd
cmp ah,74
je minus_he
cmp ah,75
je minus_hd
cmp ah,76
je plus_me
cmp ah,77
je plus_md
cmp ah,78
je minus_me
cmp ah,79
je minus_md
cmp ah,80
je reset
cmp ah,81
je set_date
cmp ah,2 ; drop down list
jne no_dropdn
.drop:
mov [focus],2
cmp [dropped],al ; ==0
jne red
call draw_window
mov edx,1 shl 31+231
mov ecx,31
mov eax,8
.bremove:
mcall
dec edx
loop .bremove
call draw_dropdown
jmp still
no_dropdn:
cmp ah,3 ; year -1
jne noy_dn
year_dec:
dec [Year]
mov [focus],3
jmp upd
noy_dn:
cmp ah,4 ; year+1
jne noy_up
year_inc:
inc [Year]
mov [focus],3
jmp upd
noy_up:
cmp ah,5
jne noy_click
mov [focus],3
call draw_window
.still:
mcall 10
cmp eax,2
jne still.evt
mcall 2
.year_evt:
cmp ah,176
je year_dec
cmp ah,179
je year_inc
mov ebx,10
cmp ah,9
je key.tab
cmp ah,8 ; backspace
jne .nobsp
mov eax,[Year]
xor edx,edx
div ebx
.ch_year:
mov [Year],eax
call draw_year
jmp .still
.nobsp:
cmp ah,13 ; enter
je upd
cmp ah,182
jne .noclear ; del
xor eax,eax
jmp .ch_year
.noclear:
cmp ah,48
jb .still
cmp ah,57
ja .still
cmp [Year],1000
jae .still
shr eax,8
lea ecx,[eax-48]
mov eax,[Year]
imul eax,ebx
add eax,ecx
jmp .ch_year
noy_click:
cmp ah,10
jne START
xor [new_style],1
jmp upd
reset:
mcall 3
mov ecx,eax
shl ecx,16
shr ecx,16
mcall 22,0x00000000
jmp still
plus_hd:
mcall 3
mov ecx,eax
add ecx,1
mcall 22,0x00000000
jmp still
plus_he:
mcall 3
mov ecx,eax
add ecx,16
mcall 22,0x00000000
jmp still
minus_hd:
mcall 3
mov ecx,eax
sub ecx,1
mcall 22,0x00000000
jmp still
minus_he:
mcall 3
mov ecx,eax
sub ecx,16
mcall 22,0x00000000
jmp still
plus_md:
mcall 3
mov ecx,eax
add ecx,256
mcall 22,0x00000000
jmp still
plus_me:
mcall 3
mov ecx,eax
add ecx,4096
mcall 22,0x00000000
jmp still
minus_md:
mcall 3
mov ecx,eax
sub ecx,256
mcall 22,0x00000000
jmp still
minus_me:
mcall 3
mov ecx,eax
sub ecx,4096
mcall 22,0x00000000
jmp still
set_date:
mov eax,0x00000000
mov ebx,[day_sel]
call additem
shl eax,8
mov ebx,[Month]
add ebx,1
call additem
shl eax,8
mov ebx,[Year]
call additem
mov ecx,eax
mcall 22,1
jmp START
additem:
add eax,1
daa
sub ebx,1
cmp ebx,0
jne additem
ret
; *********************************************
; ******* DRAW WINDOW *******
; *********************************************
draw_clock:
mcall 3
mov ecx,eax
mcall 47,0x00020100, ,195*65536+298,0x50CCCCCC,COL_TOOLBAR_BG
shr ecx,8
add edx,22*65536
mcall
shr ecx,8
add edx,22*65536
mcall
ret
define_window:
mcall 12,1
mcall 48, 5 ; GetClientTop, fix for case when @patel in the top
shr ebx, 16
mov ecx,ebx
shl ecx,16
cmp ecx,0
jne panel_top
; panel bottom
mcall 48,5 ;get screen size
mov ecx, ebx
sub ecx, WIN_H
shl ecx, 16
panel_top:
add ecx, WIN_H ; [y start] *65536 + [y size]
mov ebx, eax
sub eax, WIN_W
shl ebx, 16
add ebx, WIN_W
mcall 0,,,COL_WINDOW_BG, ,title ; define window
mcall 12,2
GetSkinHeight
mov ecx, eax
shl ecx, 16
add ecx, 43
mcall 13,B_WBAR_X, ,COL_TOOLBAR_BG ; draw toolbar background
mcall 13,B_WBAR_X,BT_WBAR_Y,COL_TOOLBAR_BG ; draw toolbar background
mcall 13,0*65536+B_WBAR_X,84*65536+199,0xE7E7E7
draw_window:
call draw_clock
call draw_week
mcall 8,193*65536+8,285*65536+10,72,COL_TOOLBAR_BG
mov ebx,202*65536+8
inc edx ;73
mcall
mov ebx,193*65536+8
mov ecx,315*65536+10
inc edx ;74
mcall
mov ebx,202*65536+8
inc edx ;75
mcall
mov ebx,215*65536+8
mov ecx,285*65536+10
inc edx ;76
mcall
mov ebx,224*65536+8
inc edx ;77
mcall
mov ebx,215*65536+8
mov ecx,315*65536+10
inc edx ;78
mcall
mov ebx,224*65536+8
inc edx ;79
mcall
mov ebx,25*65536+110
mov ecx,293*65536+22
mov esi,COL_TOOLBAR_BG
mov edx,81
mcall
mov esi,COL_MONTH_YEAR_B ; new style
mov edx,10
or edx,1 shl 29+1 shl 30
mov ebx,B_NS_X
mov ecx,B_NS_Y
mcall
add edx,1-1 shl 29
mov ebx,B_TODAY_X+8*(today_end-today_msg)
mov ecx,B_TODAY_Y
mcall
mov ecx,B_Y
mov ebx,B_MONTH_X
mov edx,2
mcall
mov ebx,B_SPIN_X ; <
inc edx
mcall
add ebx,55 shl 16 ; >
inc edx
mcall
call draw_days
; draw text in window
mcall 4,157*65536+301,0x80CCCCCC,sys_text
mcall ,211*65536+301,,separator
mcall ,233*65536+301
mcall ,185*65536+287, ,plus
mcall ,185*65536+317, ,minus
mcall , 35*65536+300,0x00CCCCCC,set_date_t,15 ;set date text
mov ecx,COL_GO_TODAY_T
mov edx,today_msg
mov ebx,B_TODAY
mov esi,today_end-today_msg
mcall
mov ebx,B_SPIN
mov edx,spinner
mov esi,8
mov ecx,COL_DROPDOWN_T
mcall
mov edx,[Month]
movzx esi,byte[month_name]
imul edx,esi
add edx,month_name+1
mov ebx,B_MONTH
ShowFocus 2
mcall
call draw_year
mov [dropped],0
ret
draw_year:
ShowFocus 3,esi
mcall 47,0x40001,Year,B_YEAR
ret
draw_dropdown:
mov [dropped],1
push [Month]
pop [focus]
add [focus],100
mov ecx,12
mov edx,100
push dword month_name+1
push dword B_DROP
push dword B_Y+16 shl 16
.ddd_loop:
mov edi,edx
push ecx
mov esi,COL_DROPDOWN_BG
mcall 8,B_MONTH_X,[esp+4]
mov eax,4
mov ebx,[esp+8]
xchg edx,[esp+12]
movzx esi,byte[month_name]
ShowFocus edi
mcall
add edx,esi
xchg edx,[esp+12]
add dword[esp+8],16
add dword[esp+4],16 shl 16
inc edx
pop ecx
loop .ddd_loop
add esp,12
ret
draw_week:
mov eax,13
mov ebx,B_WBAR_X
mov ecx,B_WBAR_Y
mov edx,COL_WEEKDAY_BG
mcall
movzx esi,byte[week_days]
movzx edi,byte[week_days+1]
mov ebx,B_WEEK
mov ecx,7
mov edx,week_days+2
mov eax,4
.week:
push ecx
cmp ecx,edi
je .holiday
mov ecx,0x10000000
jmp .noholiday
.holiday:
mov ecx,0x10cc1010
.noholiday:
mcall
add edx,esi
add ebx,B_WX_SHIFT
pop ecx
loop .week
ret
draw_days:
call count_days
cmp ecx,[day_sel]
jae .ok
mov [day_sel],ecx
.ok:
mov [number],0
mov eax,47
mov edx,B_DAYS_Y
mov ebx,0x10001
mov edi,[firstday]
push ecx
.dayloop:
movzx edx,dx
mov esi,edi
shl esi,21
lea edx,[edx+esi+34 shl 16]
mov ecx,edi
add cl,[week_days+1]
cmp ecx,7
je .holiday
mov esi,0x10313138 ; COL_DATE_TEXT
jmp .noholiday
.holiday:
mov esi,0x10cc1010
.noholiday:
mov ecx,number
inc dword[ecx]
pusha
sub edx,8 shl 16 + 8
mov ebx,edx
mov bx,DATE_BUTTON_WIDTH-1
shrd ecx,edx,16
mov cx,DATE_BUTTON_HEIGHT-1
mov edx,[number]
cmp edx,[day_sel]
je .draw_sel
mov esi,COL_DATE_BUTTONS
jmp .draw_but
.draw_sel: ;draw selected button
add edx,1 shl 30
add edx,200+1 shl 29
mcall 8
cmp [focus],4
jne .not_active
DrawRect COL_DATE_ACTIVE_1,COL_DATE_ACTIVE_2,COL_DATE_ACTIVE_3,COL_DATE_ACTIVE_4
jmp .out
.not_active:
DrawRect COL_DATE_INACTIVE_1,COL_DATE_INACTIVE_2,COL_DATE_INACTIVE_3,COL_DATE_INACTIVE_4
jmp .out
.draw_but: ;draw non selected button
add edx,200+1 shl 29
mcall 8
DrawRect COL_DATE_1,COL_DATE_2,COL_DATE_3,COL_DATE_4
mov eax,[Year]
cmp [curYear],eax
jne .out
mov eax,[Month]
cmp [curMonth],eax
jne .out
mov eax,[number]
cmp [curDay],eax
jne .out
mov edx,0xff0000
mov bx,DATE_BUTTON_WIDTH-1
mov cx,3
sub ebx,2 shl 16
sub ecx,1 shl 16
mcall 13
.out:
mov eax, [number]
xor edx, edx
mov ecx, 10
div ecx
mov [remainder], edx
mov [quotient], eax
popa
; first number
mov ecx,quotient
mcall
add edx,1 shl 16
mcall
; second number
mov ecx,remainder
add edx,8 shl 16
mcall
add edx,1 shl 16
mcall
sub edx,10 shl 16
inc edi
cmp edi,7
jne .nowrap
xor edi,edi
add dx,B_DAYS_SHIFT
.nowrap:
dec dword [esp]
jnz .dayloop
pop ecx
ret
count_days: ; ecx -days in month
call is_leap_year
mov ecx,[Month]
mov eax,1
movzx ecx,byte[day_count+ecx]
add ecx,28
cmp eax,[leap_year]
jne .noleap
cmp eax,[Month]
jne .noleap
inc ecx
.noleap:
mov [day_bounds+3],cl
mov [day_bounds+7],cl
ret
is_leap_year:
mov [leap_year],0
mov eax,[Year]
mov bl,100
div bl ; ah=Year mod 100, al=Year%100
test ah,ah
jz .century
shr ax,8 ; ax - last 2 digits
.century:
test al,11b
jnz .noleap
inc [leap_year]
.noleap:
ret
calculate:
mov ebx,[Year]
mov eax,[Month]
sub eax,2
jge .nojf
dec ebx
add eax,12
.nojf:
add eax,4
xor edx,edx
mov ecx,153
imul cx
mov ecx,5
div cx
inc eax
mov ecx,365
imul ecx,ebx
add eax,ecx
mov ecx,ebx
shr ecx,2
add eax,ecx
dec eax
add eax,2
xchg eax,ebx
mov ecx,100
xor edx,edx
div cx
sub ebx,eax
shr eax,2
add ebx,eax
add ebx,5
mov eax,ebx
xor edx,edx
movzx ebx,byte[week_days+1]
sub eax,ebx
inc eax
mov ebx,7
div bx
mov [firstday],edx
ret
I_END: