; CALENDAR FOR MENUET v1.0 ; Written in pure assembler by Ivushkin Andrey aka Willow ; ; ; Created: November 1, 2004 ; Last changed: January 13, 2005 ; ; COMPILE WITH FASM WIN_X equ (150 shl 16+270) WIN_Y equ (100 shl 16+300) LINE1 equ 27 shl 16+16 B_MONTH_X equ 10 shl 16+158 B_Y equ LINE1 B_MONTH equ 63 shl 16+32 B_WBAR_X equ 10 shl 16+250 B_WBAR_Y equ 64 shl 16+20 B_WEEK equ 30 shl 16+70 B_WX_SHIFT equ 32 shl 16 B_DBAR_X equ B_WBAR_X B_DBAR_Y equ 85 shl 16+190 B_DROP equ B_MONTH+16 B_DAYS_Y equ 100 B_DAYS_SHIFT equ 30 B_YEAR_X equ 173 shl 16+58 B_YEAR equ 188 shl 16+32 B_TODAY_X equ 25 shl 16 B_TODAY_Y equ 48 shl 16+10 B_TODAY equ 30 shl 16+50 B_SPIN_WIDTH equ 13 B_SPIN_X equ 234 shl 16+B_SPIN_WIDTH B_SPIN equ 238 shl 16+32 B_DATE_X equ 26 shl 16+60 B_DATE_Y equ 275 shl 16+16 B_DATE_BSHIFT equ 80 shl 16 B_DATE equ 32 shl 16+280 B_DATE_SHIFT equ 80 shl 16 B_NS_X equ 185 shl 16+75 B_NS_Y equ 48 shl 16+10 B_NS equ 190 shl 16+50 FOCUSABLE equ 5 SKIP equ 1 use32 ; включить 32-битный режим ассемблера org 0x0 ; адресация с нуля db 'MENUET01' ; 8-байтный идентификатор MenuetOS dd 0x01 ; версия заголовка (всегда 1) dd start ; адрес метки, с которой начинается выполнение программ dd I_END ; размер программы dd 0x1000 ; количество памяти dd 0x1000 ; адрес вершины стэка dd 0x0 ; адрес буфера для строки параметров (не используется) dd 0x0 ; зарезервировано include 'lang.inc' include 'macros.inc' ; уменьшает размер программы ;include 'debug.inc' macro ShowFocus field,reg { local .nofocus, .exit cmp [focus],field jne .nofocus if reg eq mov ecx,0x10e7c750;0x10ddeeff else mov reg,0x10e7c750;0x10ddeeff end if jmp .exit .nofocus: if reg eq mov ecx,0x10000000 else mov reg,0x10000000 end if .exit: } month_name: if lang eq ru db 8 db 'Январь ' db 'Февраль ' db 'Март ' db 'Апрель ' db 'Май ' db 'Июнь ' db 'Июль ' db 'Август ' db 'Сентябрь' db 'Октябрь ' db 'Ноябрь ' db 'Декабрь ' else if lang eq de db 9 db 'Januar ' db 'Februar ' db 'M┴rz ' db 'April ' db 'Mai ' db 'Juni ' db 'Juli ' db 'August ' db 'September' db 'Oktober ' db 'November ' db 'Dezember ' else if lang eq fr db 9 db 'Janvier ' db 'Fevrier ' db 'Mars ' db 'Avril ' db 'Mai ' db 'Juin ' db 'Juliet ' db 'Aout ' db 'Septembre' db 'Octobre ' db 'Novembre ' db 'Decembre ' else if lang eq fi db 9 db 'Tammikuu ' db 'Helmikuu ' db 'Maaliskuu' db 'Huhtikuu ' db 'Toukokuu ' db 'Kes┴kuu ' db 'Hein┴kuu ' db 'Elokuu ' db 'Syyskuu ' db 'Lokakuu ' db 'Marraskuu' db 'Joulukuu ' else db 9 db 'January ' db 'February ' db 'March ' db 'April ' db 'May ' db 'June ' db 'July ' db 'August ' db 'September' db 'October ' db 'November ' db 'December ' end if spinner db '< >' week_days: if lang eq ru db 2 db 1 db 'Пн' db 'Вт' db 'Ср' db 'Чт' db 'Пт' db 'Сб' db 'Вс' else if lang eq de db 2 db 7 db 'So' db 'Mo' db 'Di' db 'Mi' db 'Do' db 'Fr' db 'Sa' else if lang eq fr db 3 db 7 db 'Dim' db 'Lun' db 'Mar' db 'Mer' db 'Jeu' db 'Ven' db 'Sam' else if lang eq fi db 2 db 7 db 'Su' db 'Ma' db 'Ti' db 'Ke' db 'To' db 'Pe' db 'La' else db 3 db 7 db 'Sun' db 'Mon' db 'Tue' db 'Wen' db 'Thi' db 'Fri' db 'Sat' end if str2int: xor eax,eax lodsb mov ebx,eax shr ebx,4 and eax,0xf imul ebx,10 add al,bl ret start: mcall 29 mov [datestr],eax mov esi,datestr call str2int add eax,1900 mov [Year],eax call str2int dec eax mov [Month],eax call str2int mov [day_sel],eax test byte[esi],0 jnz .no2000 add [Year],100 .no2000: jmp upd ; здесь начинается выполнение программы red: ; перерисовать окно call draw_window ; вызываем процедуру отрисовки окна still: ; ГЛАВНЫЙ ЦИКЛ ПРОГРАММЫ mov eax,10 ; функция 10 - ждать события int 0x40 ; вызываем систему .evt: mov ebp,[focus] cmp eax,1 ; перерисовать окно ? je red ; если да - на метку red cmp eax,2 ; нажата клавиша ? je key ; если да - на key cmp eax,3 ; нажата кнопка ? je button ; если да - на button jmp still ; если другое событие - в начало цикла key: ; нажата клавиша на клавиатуре mov eax,2 ; функция 2 - считать код символа int 0x40 ; вызов системы cmp ah,9 jne no_tab .tab: cmp ebp,FOCUSABLE je 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,4 jne no_spinner cmp ah,176 je year_dec cmp ah,179 je year_inc no_spinner: cmp ebp,2 jne .nomonth cmp ah,177 je noclose.drop jmp still .nomonth: cmp ebp,3 je noy_up.year_evt cmp ebp,5 jne still mov ebx,[day_sel] cmp ah,176 ; left arrow jb still cmp ah,179 ja 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: ; нажата кнопка в окне программы mov eax,17 ; 17 - получить идентификатор нажатой кнопки int 0x40 ; вызов системы 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],5 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 ; идентификатор == 1 ? jne noclose ; если нет - иди вперёд на noclose close: or eax,-1 ; выход из программы int 0x40 ; вызов системы noclose: 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: int 0x40 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],4 jmp upd noy_dn: cmp ah,4 ; year+1 jne noy_up year_inc: inc [Year] mov [focus],4 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: 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 ; ********************************************* ; ******* ОПРЕДЕЛЕНИЕ И ОТРИСОВКА ОКНА ******* ; ********************************************* draw_window: mov eax,12 ; функция 12: сообщить ОС об отрисовке окна mov ebx,1 ; 1 - начинаем рисовать int 0x40 ; СОЗДАЁМ ОКНО xor eax,eax ; функция 0 : определить и отрисовать окно mov ebx,WIN_X if SKIP eq 0 mov ecx,WIN_Y else mov ecx,WIN_Y-15 end if mov edx,0x03aabbcc ; цвет рабочей области RRGGBB,8->color gl mov esi,0x805080d0 ; цвет полосы заголовка RRGGBB,8->color gl mov edi,0x005080d0 ; цвет рамки RRGGBB int 0x40 call draw_week mov eax,8 mov esi,0x05080d0 if SKIP eq 0 mov ebx,B_DATE_X mov ecx,B_DATE_Y mov edx,eax int 0x40 inc edx add ebx,B_DATE_BSHIFT int 0x40 inc edx else mov edx,10 end if or edx,1 shl 29+1 shl 30 mov ebx,B_NS_X mov ecx,B_NS_Y int 0x40 add edx,1-1 shl 29 mov ebx,B_TODAY_X+8*(today_end-today_msg) mov ecx,B_TODAY_Y int 0x40 mov ecx,B_Y mov ebx,B_MONTH_X mov edx,2 int 0x40 mov ebx,B_SPIN_X inc edx int 0x40 add ebx,B_SPIN_WIDTH shl 16 inc edx int 0x40 call draw_days ; ЗАГОЛОВОК ОКНА mov eax,4 ; функция 4 : написать в окне текст mov ebx,8*65536+8 ; [x] *65536 + [y] mov ecx,0x10ddeeff ; шрифт 1 и цвет ( 0xF0RRGGBB ) mov edx,zagolovok ; адрес строки mov esi,zag_konets-zagolovok ; и её длина int 0x40 if SKIP eq 0 mov ebx,B_DATE mov edx,datebut mov esi,9 btc ecx,28 int 0x40 add ebx,B_DATE_SHIFT add edx,esi int 0x40 end if mov edx,n_style mov esi,ns_end-n_style mov ebx,B_NS cmp [new_style],1 je .high mov ecx,0xa0a0a0 jmp .int .high: mov ecx,0xac0000;d048c8 .int: int 0x40 mov ecx,0xd048c8 mov edx,today_msg mov ebx,B_TODAY mov esi,today_end-today_msg int 0x40 mov ebx,B_SPIN mov edx,spinner mov esi,3 ShowFocus 4 int 0x40 mov edx,[Month] movzx esi,byte[month_name] imul edx,esi add edx,month_name+1 mov ebx,B_MONTH ShowFocus 2 int 0x40 call draw_year mov [dropped],0 mov eax,12 ; функция 12: сообщить ОС об отрисовке окна mov ebx,2 ; 2, закончили рисовать int 0x40 ret ; выходим из процедуры draw_year: mcall 8,B_YEAR_X,B_Y,5,0x05080d0 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 ebx,B_MONTH_X mov ecx,[esp+4] mov esi,0x6f9fef mov eax,8 int 0x40 shr eax,1 mov ebx,[esp+8] xchg edx,[esp+12] movzx esi,byte[month_name] ShowFocus edi int 0x40 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,0x90a0b0 int 0x40 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: int 0x40 add edx,esi add ebx,B_WX_SHIFT pop ecx loop .week ret draw_days: mov eax,13 mov ebx,B_DBAR_X mov ecx,B_DBAR_Y mov edx,0xe0e0e0 int 0x40 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,0x20001 mov edi,[firstday] .dayloop: push ecx movzx edx,dx mov esi,edi shl esi,21 lea edx,[edx+esi+30 shl 16] mov ecx,edi add cl,[week_days+1] cmp ecx,7 je .holiday mov esi,0x10000000 jmp .noholiday .holiday: mov esi,0x10cc1010 .noholiday: mov ecx,number inc dword[ecx] pusha mov ebx,edx mov bx,20 sub ebx,3 shl 16 shrd ecx,edx,16 mov cx,20 sub ecx,7 shl 16 mov edx,[number] cmp edx,[day_sel] je .draw_sel mov esi,0xe0e0e0 jmp .draw_but .draw_sel: mov esi,0x5080d0 cmp [focus],5 jne .draw_but mov esi,0xef7840;0xe26830 .draw_but: add edx,200+1 shl 29 mov eax,8 int 0x40 popa int 0x40 pop ecx inc edi cmp edi,7 jne .nowrap xor edi,edi add dx,B_DAYS_SHIFT .nowrap: loop .eloop jmp .ex .eloop: jmp .dayloop .ex: 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 cmp [new_style],0 je .nonew add eax,2 xchg eax,ebx mov ecx,100 xor edx,edx div cx sub ebx,eax shr eax,2 add ebx,eax .nonew: 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 ; Здесь находятся данные программы: ; интерфейс программы двуязычный - задайте язык в macros.inc day_count db 3,0,3,2,3,2,3,3,2,3,2,3 Fkeys db 210,211,212,213,214,215,216,217,208,209,228,159 zagolovok: ; строка заголовка if lang eq ru db 'КАЛЕНДАРЬ' else if lang eq ge db 'KALENDER' else if lang eq fr db 'CALENDRIER' else db 'CALENDAR' end if zag_konets: ; и её конец if SKIP eq 0 datebut: if lang eq ru db '1-я дата ' db '2-я дата ' else if lang eq fr db '1ere date' db '2eme date' else if lang eq ge db ' Datum 1 ' db ' Datum 2 ' else db '1st date ' db '2nd date ' end if end if n_style: if lang eq ru db 'Новый стиль' else if lang eq de db 'Neuer Stil' else if lang eq fr db 'Nouveau' else db 'New style' end if ns_end: today_msg: if lang eq ru db 'Сегодня' else if lang eq ge db 'Heute' else if lang eq fr db "Aujourd'hui" else db 'Today' end if today_end: focus dd 3 new_style dd 1 dropped db 0 I_END: ; конец программы firstday dd ? Year dd ? Month dd ? day_sel dd ? all_days dd ? datestr dd ? leap_year dd ? number dd ? year_input dd ?