include	clib.inc
include	time.inc
include	conio.inc
include	mouse.inc
include	keyb.inc
include	format.inc

STARTDAY  	= 5
STARTYEAR       = 0
MAXYEAR 	= 3000

USE_MDALTKEYS	= 1

_DATA	SEGMENT

;******** Resource begin CALENDAR *
;	{ 0x005C,   0,   0, {42, 2,29,10} },
;******** Resource data  *******************
CALENDAR_RC label word
	dw	00283h	; Alloc size
	dw	0005Ch,00000h,0022Ah,00A1Dh,03AF0h,0F02Eh,02A3Ah,01DF0h
	dw	0F02Eh,02A74h,01DF0h,0F02Eh,0DF1Dh,04D20h,06E6Fh,05420h
	dw	06575h,05720h,06465h,05420h,07568h,04620h,06972h,05320h
	dw	07461h,05320h,06E75h,02020h,01BF0h,0F0C4h,020AFh,01DF0h
	dw	02EDCh
;	68 byte
;******** Resource end   CALENDAR *

;******** Resource begin CALENDAR2 *
;	{ 0x0010,   0,   0, {45,12,14, 1} },
;******** Resource data  *******************
CALENDAR2_RC label word
	dw	0002Ch	; Alloc size
	dw	00010h,00000h,00C2Dh,0010Eh,00EF0h,0F007h,0200Eh,00707h
;	18 byte
;******** Resource end   CALENDAR2 *

cp_jan	db	"January",0
cp_feb	db	"February",0
cp_mar	db	"March",0
cp_apr	db	"April",0
cp_may	db	"May",0
cp_jun	db	"June",0
cp_jul	db	"July",0
cp_aug	db	"August",0
cp_sep	db	"September",0
cp_oct	db	"October",0
cp_nov	db	"November",0
cp_dec	db	"December",0

cp_month label word
	dw	offset cp_jan
	dw      offset cp_feb
	dw      offset cp_mar
	dw      offset cp_apr
	dw      offset cp_may
	dw      offset cp_jun
	dw      offset cp_jul
	dw      offset cp_aug
	dw      offset cp_sep
	dw      offset cp_oct
	dw      offset cp_nov
	dw      offset cp_dec

mnd_table  db	31,28,31,30,31,30,31,31,30,31,30,31
keypos db	1,5,9,13,17,21,25

keylocal label word
	dw	MOUSECMD
	dw	KEY_ESC
	dw	KEY_HOME
	dw	KEY_RIGHT
	dw	KEY_LEFT
	dw	KEY_UP
	dw	KEY_DOWN
	dw	KEY_PGUP
	dw	KEY_PGDN
	dw	KEY_CTRLPGUP
	dw	KEY_CTRLPGDN
	dw	KEY_ENTER
	dw	KEY_ALTX
ifdef USE_MDALTKEYS
	dw	KEY_ALTUP
	dw	KEY_ALTDN
	dw	KEY_ALTLEFT
	dw	KEY_ALTRIGHT
endif

keyproc label word
	dw	event_mouse
	dw	event_ESC
	dw	event_HOME
	dw	event_nextday
	dw	event_prevday
	dw	event_UP
	dw	event_DOWN
	dw	event_prevmnd
	dw	event_nextmnd
	dw	event_prevyear
	dw	event_nextyear
	dw	event_ENTER
	dw	event_ESC
ifdef USE_MDALTKEYS
	dw	event_ALTUP
	dw	event_ALTDN
	dw	event_ALTLEFT
	dw	event_ALTRIGHT
keycount =	17
else
keycount =	13
endif

_DATA	ENDS

_TEXT	SEGMENT

DAYS_IN_FEB:
	push	dx
	push	bx
	or	cx,cx
	jz	days_in_feb_29
	mov	ax,cx
	and	al,3
	jnz	@F
	mov	ax,cx
	mov	bx,100
	xor	dx,dx
	div	bx
	or	dx,dx
	jnz	days_in_feb_29
      @@:
	mov	bx,400
	mov	ax,cx
	xor	dx,dx
	div	bx
	or	dx,dx
	jz	days_in_feb_29
	mov	ax,28
    days_in_feb_end:
	pop	bx
	pop	dx
	ret
    days_in_feb_29:
	mov	ax,29
	jmp	days_in_feb_end

DAYS_IN_MND:
	cmp	bx,2
	je	DAYS_IN_FEB
	mov	ah,0
	mov	al,mnd_table[bx-1]
	ret

WEEKDAY_JAN1:
	push	bp
	push	si
	push	di
	xor	bp,bp
	mov	si,STARTDAY
	mov	di,cx
	mov	cx,STARTYEAR
    weekday_jan1_loop:
	cmp	cx,di
	jnb	weekday_jan1_break
	call	DAYS_IN_FEB
	cmp	ax,29
	jne	@F
	add	si,1
	adc	bp,0
    @@:
	inc	cx
	add	si,1
	adc	bp,0
	jmp	weekday_jan1_loop
    weekday_jan1_break:
	push	dx
	mov	dx,bp
	mov	ax,si
	mov	si,7
	div	si
	mov	ax,dx
	pop	dx
	mov	cx,di
	pop	di
	pop	si
	pop	bp
	ret

GETWEEKDAY:
	call	WEEKDAY_JAN1
	push	si
	push	di
	mov	si,ax
	mov	di,bx
	mov	bx,1
    @@:
	cmp	bx,di
	jnb	@F
	call	DAYS_IN_MND
	add	si,ax
	inc	bx
	jmp	@B
    @@:
	push	dx
	mov	di,7
	xor	dx,dx
	mov	ax,si
	div	di
	mov	ax,dx
	pop	dx
	pop	di
	pop	si
	ret

GETCURDATE:		; GET SYSTEM DATE
	mov	ah,2Ah	; CX = year (1980-2099)
	int	21h	; DH = month
	xor	ah,ah	; DL = day
	mov	al,dl
	mov	[bp-22],ax
	mov	al,dh
	mov	[bp-20],ax
	mov	[bp-18],cx
	mov	dx,[bp-22]
	mov	bx,ax
	call	GETWEEKDAY
	mov	[bp-16],ax
	call	DAYS_IN_MND
	mov	[bp-14],ax
	ret

INCYEAR:
	mov	cx,[bp-18]
	cmp	cx,MAXYEAR
	je	@F
	inc	cx
	ret
    @@:
	mov	cx,STARTYEAR
	ret

DECYEAR:
	mov	cx,[bp-18]
	or	cx,cx
	jz	@F
	dec	cx
	ret
    @@:
	mov	cx,MAXYEAR
	ret

PUTMND:	mov	bx,[bp-24]
	add	bx,0A03h
	mov	cx,14
	mov	ax,0720h
	call	@scputw
	push	word ptr [bp-18]
	push	ds
	mov	ax,bx
	mov	bx,[bp-20]
	dec	bx
	add	bx,bx
	push    [bx+cp_month]
	mov	bx,ax
	mov	ax,offset format_s_d
	call	@scputf
	add	sp,6
	ret

PUTDAY:	inc	si
	push	cx
	push	di
	push	si
	mov	bx,cx
	mov	cl,02h
	mov	ch,at_background[7]
	mov	al,at_foreground[0Fh]
	cmp	si,[bp-22]
	je	@F
	mov	al,at_foreground[0]
    @@:
	or	ch,al
	mov	al,[bx+keypos]
	mov	bx,di
	mov	bl,al
	add	bx,[bp-24]
	mov	ax,offset format_2d
	call	@scputf
	add	sp,2
	mov	di,bx
	call	getday
	xor	ah,ah
	cmp	ax,si
	jne	@F
	call	getmnd
	xor	ah,ah
	cmp	ax,[bp-20]
	jne	@F
	call	getyear
	cmp	ax,[bp-18]
	jne	@F
	mov	bx,di
	mov	cx,2
	mov	al,04h
	or	al,at_background[7]
	call	@scputa
    @@:
	pop	di
	pop	cx
	ret

PUTDATE:
	push	si
	push	di
	mov	ax,[bp-18]	; year
	mov	dx,[bp-20]	; month
	cmp	ax,[bp-12]	; current year
	jne	putdate_mnd
	cmp	dx,[bp-10]	; current month
	je	putdate_day
    putdate_mnd:
	mov	[bp-10],dx
	mov	[bp-12],ax
	call	PUTMND
	mov	bx,[bp-24]
	add	bh,3
	mov	cx,29
    putdate_clr:
	mov	al,20h
	mov	ah,at_background[7]
	or	ah,at_foreground[0]
	call	@scputw
	inc	bh
	mov	al,[bp-23]
	add	al,3+6
	cmp	bh,al
	jb	putdate_clr
    putdate_day:
	xor	si,si
	mov	di,0300h
    putdate_loop:
	cmp	si,[bp-14]
	jnb	putdate_end
	xor	cx,cx
    putdate_xloop:
	cmp	cx,7
	jnb	putdate_yloop
	mov	ax,0300h	; first line
	cmp	[bp-16],cx	; week day
	ja      @F
	cmp	di,ax
	je	putdate_putday
    @@:
	cmp	di,ax
	jna	putdate_next
	cmp	si,[bp-14]	; days in month
	jae	putdate_next
    putdate_putday:
	call	PUTDAY
    putdate_next:
	inc	cx
	jmp	putdate_xloop
    putdate_yloop:
	add	di,0100h
	cmp	di,0A00h
	jb	putdate_loop
    putdate_end:
	pop	di
	pop	si
	ret

SETDATE:
	mov	[bp-22],dx	; day
	mov	[bp-20],bx	; month
	mov	[bp-18],cx	; year
	call	GETWEEKDAY
	mov	[bp-16],ax	; week day
	call	DAYS_IN_MND
	mov	[bp-14],ax	; days in month
	call	PUTDATE
	ret

ifdef USE_MDALTKEYS
event_ALTUP:
	mov	ax,offset rcmoveup
	jmp	DLMOVE_MOVE
event_ALTDN:
	mov	ax,offset rcmovedn
	jmp	DLMOVE_MOVE
event_ALTLEFT:
	mov	ax,offset rcmoveleft
	jmp	DLMOVE_MOVE
event_ALTRIGHT:
	mov	ax,offset rcmoveright
DLMOVE_MOVE:
	push	ax
	pushm	[bp-6]
	call	dlhide
	pop	ax
	les	bx,[bp-28]
	pushm	es:[bx+4]
	pushm	es:[bx+12]
	push	es:[bx]
	LPUSH	cs
	call	ax
	mov	ax,dx
	les	bx,[bp-28]
	mov	es:[bx+4],ax
	mov	[bp-24],ax
	add	ax,0A03h
	les	bx,[bp-6]
	mov	es:[bx+4],ax
	pushm	[bp-6]
	call	dlshow
	ret
endif

event_ENTER:
	mov	ax,1
	mov	[bp-8],ax

event_ESC:
	inc	byte ptr [bp-1]
	ret

event_HOME:
	call	GETCURDATE
	jmp	PUTDATE

event_nextday:
	mov	dx,[bp-22]
	inc	dx
	cmp	dx,[bp-14]
	ja	event_nextmnd
	mov	[bp-22],dx
	jmp	PUTDATE

event_prevday:
	mov	dx,[bp-22]
	cmp	dx,1
	je	@F
	mov	cx,[bp-18]
	mov	bx,[bp-20]
	dec	dx
	jmp	SETDATE
    @@:
	call	event_prevmnd
	mov	ax,[bp-14]
	mov	[bp-22],ax
	jmp	PUTDATE

event_UP:
	mov	ax,7
	cmp	[bp-22],ax
	jbe	event_prevday
	sub	[bp-22],ax
	jmp	PUTDATE

event_DOWN:
	mov	ax,[bp-22]
	add	ax,7
	cmp	ax,[bp-14]
	ja	event_nextday
	mov	[bp-22],ax
	jmp	PUTDATE

event_prevmnd:
	mov	dx,1
	mov	bx,[bp-20]
	mov	cx,[bp-18]
	cmp	bx,1
	je	@F
	dec	bx
	jmp	SETDATE
    @@:
	mov	bx,12
	call	DECYEAR
	jmp	SETDATE

event_nextmnd:
	mov	bx,[bp-20]
	cmp	bx,12
	je	event_nextyear
	mov	dx,1
	mov	cx,[bp-18]
	inc	bx
	jmp	SETDATE

event_prevyear:
	mov	dx,1
	mov	bx,dx
	call	DECYEAR
	jmp	SETDATE

event_nextyear:
	mov	dx,1
	mov	bx,dx
	call	INCYEAR
	jmp	SETDATE

event_mouse:
  ifdef __MOUSE__
	les	bx,[bp-28]
	pushm	es:[bx.dl_rect]
	call	mousex
	push	ax
	call	mousey
	push	ax
	call	rcxyrow
	or	ax,ax
	jz	event_ESC
	pushm	[bp-6]
	call	dlhide
	pushm	[bp-28]
	call	dlmove
	les	bx,[bp-28]
	mov	ax,es:[bx+4]
	mov	[bp-24],ax
	add	ax,0A03h
	les	bx,[bp-6]
	mov	es:[bx+4],ax
	pushm	[bp-6]
	call	dlshow
  else
	xor	ax,ax
  endif
	ret

modal:	cmp	byte ptr [bp-1],0
	jne	modal_end
	call	tgetevent
	mov	cx,keycount
	xor	bx,bx
    modal_cmp:
	cmp	ax,[bx+keylocal]
	je	modal_found
	add	bx,2
	loop	modal_cmp
	jmp	modal
    modal_found:
	call	word ptr [bx+keyproc]
	jmp	modal
    modal_end:
	ret

_TEXT	ENDS

PPROC	cmcalendar
local	ld[28]:byte
	xor	ax,ax
	mov     [bp-1],al
	mov     [bp-12],ax
	mov     [bp-10],ax
	mov	[bp-8],ax
	push	ds
	mov	ax,offset CALENDAR_RC
	push	ax
	call	rsopen
	jz	cmcalendar_end
	mov     [bp-28],ax
	mov     [bp-26],dx
	push	dx
	push	ax
	push	dx
	push	ax
	mov	bx,ax
	mov	ax,es:[bx+4]
	mov     [bp-24],ax
	call	dlshow
	push	ds
	mov	ax,offset CALENDAR2_RC
	push	ax
	call	rsopen
	mov     [bp-6],ax
	mov     [bp-4],dx
	push	dx
	push	ax
	push	dx
	push	ax
	call	dlshow
	call	GETCURDATE
	mov	dx,[bp-22]
	mov	bx,[bp-20]
	mov	cx,[bp-18]
	call	SETDATE
  ifdef __MOUSE__
	call	msloop
  endif
	call	modal
	call	dlclose
	call	dlclose
	mov	dx,[bp-22]
	mov	bx,[bp-20]
	mov	cx,[bp-18]
    cmcalendar_end:
	mov	ax,[bp-8]
	ret
PEND	cmcalendar

	END
