home *** CD-ROM | disk | FTP | other *** search
- {*********************************************************}
- {* TurboCal 1.00 *}
- {* Copyright (c) Kenny D. Walker 1988. *}
- {* All rights reserved. *}
- {*********************************************************}
-
-
- {*********************************************************}
- {* You are free to use this software in other software *}
- {* programs for a one time registration fee of $10.00. *}
- {* *}
- {* You are encouraged to distribute this software in *}
- {* UNMODIFIED form for others to use subject to the *}
- {* above registration. *}
- {*********************************************************}
-
- {*********************************************************}
- {* If you have any suggestions or find any bugs, please *}
- {* contact the author on Compuserve, or my mail. *}
- {* *}
- {* Kenny D. Walker *}
- {* 1819 Walthour Road *}
- {* Savannah, Georgia, 31410 *}
- {* *}
- {* Compuserve User ID: 70235,1160 *}
- {* *}
- {*********************************************************}
-
-
- unit turbocal;
-
- interface
-
- uses dos,tpcrt,tpstring;
-
- procedure calendar(x,y,current_attr,select_attr,other_attr:byte;flag:boolean;var year,month,day:word);
-
- implementation
- {$V-}
- const
- intenseattr:byte=$0F; {default attribute for days of current month}
- reverseattr:byte=$70; {default attribute for selected day}
- normalattr:byte =$07; {default attribute for days of non-current months}
- blinkattr:byte =$80; {blink attribute, ORed with other attribute to
- cause blinking of current system date}
-
- NULL = #0; {defines for ScanKey Function from MISCTOOL unit}
- BELL = #7; {MISCTOOL is a unit supplied in the Turbo Pascal}
- BS = #8; {Database Toolbox for TP4. That software is NOT}
- LF = #10; {required for operation of this unit, the necessary}
- CR = #13; {code is included here}
- ESC = #27;
- Space = #32;
- Tab = #9;
-
- { The following constants are based on the scheme used by the scan key
- function to convert a two key scan code sequence into one character
- by adding 128 to the ordinal value of the second character.
- }
- F1 = #187;
- F2 = #188;
- F3 = #189;
- F4 = #190;
- F5 = #191;
- F6 = #192;
- F7 = #193;
- F8 = #194;
- F9 = #195;
- F10 = #196;
- UpKey = #200;
- DownKey = #208;
- LeftKey = #203;
- RightKey = #205;
- PgUpKey = #201;
- PgDnKey = #209;
- HomeKey = #199;
- EndKey = #207;
- InsKey = #210;
- DelKey = #211;
- CopyRightKey = #255;
- type
-
- boxtype=array[1..242] of byte; {this is an array type used to store
- information about the month which is
- being displayed}
-
- datetype=record {type used internally, corresponds with}
- year,month,day,dayofweek:word; {the values returned by the GetDate }
- end; {procedure in TP4}
-
-
- function ScanKey : char;
- { Reads a key from the keyboard and converts 2 scan code escape
- sequences into 1 character. }
-
- var
- Ch : Char;
- begin
- Ch := ReadKey;
- if (Ch = #0) and KeyPressed then
- begin
- Ch := ReadKey;
- if ord(Ch) < 128 then
- Ch := Chr(Ord(Ch) + 128);
- end;
- ScanKey := Ch;
- end; { ScanKey }
-
- {*********************************************************}
- {* The following two functions: leap_year and *}
- {* day_of_week are from the file EXDATE.PAS which is *}
- {* available in Data Library 2 of the Borland Turbo *}
- {* Pascal SIG on Compuserve. These functions were *}
- {* authored by Ted Lassagne. *}
- {*********************************************************}
-
-
- function leap_year(year: integer) : boolean;
- { Returns true for a leap year and false for others }
- begin
- if year and 3 <> 0 then leap_year := false
- else if year mod 100 <> 0 then leap_year := true
- else if year mod 400 <> 0 then leap_year := false
- else leap_year := true;
- end;
-
- function day_of_week (day, month, year: integer) : integer;
- {Returns integer day of week for date. 0 = Sunday, 6 = Saturday
- Uses Zeller's congruence.}
- var century, yr, dw: integer;
-
- begin
- if month < 3 then begin
- month := month + 10;
- year := year -1
- end
- else
- month := month - 2;
- century := year div 100;
- yr := year mod 100;
- dw := (((26*month - 2) div 10)+day+yr+(yr div 4)+
- (century div 4) - (2*century)) mod 7;
- if dw < 0 then
- day_of_week := dw + 7
- else day_of_week := dw;
- end;
-
-
- function intstr(value: integer): string;
- {This function is merely a shell around the STR procedure, in order to
- provided the result in function form}
- var
- numstring : string;
-
- begin
- Str(Value,NumString);
- IntStr := NumString;
- end;
-
-
- procedure calendar(x,y,current_attr,select_attr,other_attr:byte;flag:boolean;var year,month,day:word);
- const
- dpm:array[0..11] of integer = (31,28,31,30,31,30,31,31,30,31,30,31);
- names:array[0..11] of string[9] = ('January','February','March','April',
- 'May','June','July','August','September',
- 'October','November','December');
-
-
- var
- tday,c,extra,mo,tyear:integer;
- daystr:string[4];
- ch:char;
- color:byte;
- yrstr:string[4];
- todaysdate:datetype; {internal storage of current system date}
- date:datetype; {internal useage of date passed in var parameters}
- buffer:pointer; {needed for use by savewindow and restorewindow}
- calbox:boxtype; {actual array variable used to store calendar. This
- array contains one byte for the character of the
- display and one byte for its attribute}
-
- calptr:pointer; {pointer to location of calbox}
-
- procedure stuffcal;
- {this is the procedure which actually places the calendar on the screen. The
- calendar is constructed in memory in its entirety and then placed on to the
- screen with the restorewindow procedure. This is actually a trick since the
- calbox window was never saved.}
- var
- count,s:integer;
- limit:integer;
- begin
- str(date.year,yrstr); {make year string for display}
- framewindow(x,y,x+21,y+8,7,7,''); {draw frame around calendar window}
-
- {write name of month on top line of calendar window}
- fastwrite(center(names[date.month-1]+' '+yrstr,20),y+1,x+1,reverseattr);
-
- {clear array each time}
- for count:=1 to 242 do
- if odd(count) then
- calbox[count]:=32 {set character to 'space'}
- else
- calbox[count]:=normalattr; {set attribute for character}
-
- count:=1;
-
- {get day of week for the month in question}
- tday:=day_of_week(1,integer(date.month),integer(date.year));
-
- tyear:=date.year;
- mo:=date.month-1; {constant dpm and names arrays are zero based}
-
- color:=normalattr; {set attribute to low intensity for days of month
- which precede month to be displayed}
- s:=0;
- c:=0;
-
- {set up calendar for last days of previous month}
- if(tday>0) then
- for s:=0 to tday-1 do begin
- if((mo-1=1) and (leap_year(date.year))) then {if the last month was }
- extra:=2 {February, check for }
- else {leap year}
- extra:=1;
- if(mo=0) then
- daystr:=intstr((dpm[mo]+s-tday+extra)) {make 2 character string}
- else {for number value of day}
- daystr:=intstr((dpm[mo-1]+s-tday+extra)); {pad left with blank for}
- daystr:=leftpad(daystr,2); {single digit days}
-
- calbox[count]:=ord(daystr[1]); {for each day, place ord}
- calbox[count+1]:=color; {value of string char in}
- calbox[count+2]:=ord(daystr[2]); {array, followed by attr}
- calbox[count+3]:=color; {for that value. Each }
- calbox[count+4]:=32; {day needs to be followed}
- calbox[count+5]:=color; {by a space character for}
- c:=c+1; {separation from the next}
- count:=count+6; {day }
- end;
-
- tday:=1;
- color:=intenseattr; {change color to that for days of month to be
- displayed}
-
- while (tday<=dpm[mo]) do begin
- daystr:=intstr(tday);
- daystr:=leftpad(daystr,2);
- if(tday=date.day) then begin
- calbox[count]:=ord(daystr[1]); {as above stuff array with values}
- calbox[count+1]:=reverseattr; {and attributes. This section }
- calbox[count+2]:=ord(daystr[2]); {tests to see if day being }
- calbox[count+3]:=reverseattr; {stuffed is the current selection}
- calbox[count+4]:=32; {day and if so, sets attribute to}
- calbox[count+5]:=color; {the attribute for selected day }
- end
- else begin
- calbox[count]:=ord(daystr[1]); {if day being stuffed was NOT the}
- calbox[count+1]:=color; {selected day, then attribute is }
- calbox[count+2]:=ord(daystr[2]); {the attribute for days of current}
- calbox[count+3]:=color; {month}
- calbox[count+4]:=32;
- calbox[count+5]:=color;
- end;
- if((tday=todaysdate.day) and (mo=todaysdate.month-1) and
- (tyear=todaysdate.year) and (flag)) then begin
- calbox[count+1]:=(calbox[count+1] or blink); {if the day being stuffed}
- calbox[count+3]:=(calbox[count+3] or blink); {is the current day as in}
- end; {system date cause to }
- {blink }
-
- tday:=tday+1;
- c:=c+1;
- count:=count+6;
- if(c>6) then begin
- c:=0;
- count:=count-2;
- end;
- end;
-
- {the following sections makes adjustments to February for leap year}
- if((mo=1) and (leap_year(date.year))) then begin
- daystr:=intstr(tday);
- daystr:=leftpad(daystr,2);
- c:=c+1;
- calbox[count]:=ord(daystr[1]);
- if(date.day<>29) then
- calbox[count+1]:=color
- else
- calbox[count+1]:=reverseattr;
- calbox[count+2]:=ord(daystr[2]);
- if(date.day<>29) then
- calbox[count+3]:=color
- else
- calbox[count+3]:=reverseattr;
- calbox[count+4]:=32;
- calbox[count+5]:=color;
- count:=count+6;
- end;
-
- color:=normalattr; {set attribute back in order to display days of}
- if(c>0) then {month which follow the displayed month}
- for s:=1 TO 7-c do begin
- daystr:=intstr(s);
- daystr:=leftpad(daystr,2); {stuff days as before}
- calbox[count]:=ord(daystr[1]);
- calbox[count+1]:=color;
- calbox[count+2]:=ord(daystr[2]);
- calbox[count+3]:=color;
- calbox[count+4]:=32;
- calbox[count+5]:=color;
- count:=count+6;
- end;
-
- calptr:=@calbox; {set pointer to point to calendar array, this is the
- trick which allows restore window to restore a window
- which has never been saved}
-
- restorewindow(x+1,y+2,x+20,y+7,false,calptr);
- end;
-
-
- {this procedure is used to adjust the displayed month based upon the key
- pressed while in the selection mode}
- procedure getcalkey(var date:datetype);
- var
- chr1,chr2:char;
- tempdate:datetype;
- n:integer;
- oldxy,scanlines:word;
- begin
- getcursorstate(oldxy,scanlines); {hide the cursor}
- hiddencursor;
- tempdate:=date;
- repeat
- date:=tempdate;
- stuffcal; {draw calendar}
- chr1:=scankey; {get keypress}
- case chr1 of
- CR:begin {this accepts the date displayed}
- end;
- ESC:begin {exit set date values to 0}
- tempdate.year:=0;
- tempdate.month:=0;
- tempdate.day:=0;
- end;
- LeftKey:if tempdate.day>1 then {decrement day value}
- tempdate.day:=tempdate.day-1
- else
- if tempdate.month>1 then begin
- tempdate.month:=tempdate.month-1;
- tempdate.day:=dpm[tempdate.month-1];
- if((tempdate.month=2) and (leap_year(tempdate.year))) then
- tempdate.day:=29;
- end
- else begin
- if(tempdate.year>1) then
- tempdate.year:=tempdate.year-1;
- tempdate.month:=12;
- tempdate.day:=31;
- end;
- RightKey:if tempdate.day<dpm[tempdate.month-1] then {increment day value}
- tempdate.day:=tempdate.day+1
- else
- if((tempdate.month=2) and (leap_year(tempdate.year))) then
- if(tempdate.day<>29) then
- tempdate.day:=29
- else begin
- tempdate.day:=1;
- tempdate.month:=tempdate.month+1;
- end
- else
- if tempdate.month<12 then begin
- tempdate.month:=tempdate.month+1;
- tempdate.day:=1;
- end
- else begin
- if(tempdate.year<65535) then
- tempdate.year:=tempdate.year+1;
- tempdate.month:=1;
- tempdate.day:=1;
- end;
- UpKey:if tempdate.month>1 then begin {decrement month value}
- tempdate.month:=tempdate.month-1;
- if tempdate.day>dpm[tempdate.month-1] then
- tempdate.day:=dpm[tempdate.month-1];
- end
- else begin
- tempdate.month:=12;
- if(tempdate.year>1) then
- tempdate.year:=tempdate.year-1;
- end;
- DownKey:if tempdate.month<12 then begin {increment month value}
- tempdate.month:=tempdate.month+1;
- if tempdate.day>dpm[tempdate.month-1] then
- tempdate.day:=dpm[tempdate.month-1];
- end
- else begin
- if(tempdate.year<65535) then
- tempdate.year:=tempdate.year+1;
- tempdate.month:=1;
- end;
- PgUpKey:begin {increment year value}
- if(tempdate.year>1) then begin
- tempdate.year:=tempdate.year-1;
- if((tempdate.month=2) and (tempdate.day=29)) then
- tempdate.day:=28;
- end;
- end;
- PgDnKey:begin {decrement year value}
- if(tempdate.year<65535) then begin
- tempdate.year:=tempdate.year+1;
- if((tempdate.month=2) and (tempdate.day=29)) then
- tempdate.day:=28;
- end;
- end;
- {this following keypress value can be remove, but NOT altered, it diplays
- a small copyright notice in the calendar window and pauses for a keypress}
- CopyRightKey:begin
- fastwrite(center('TurboCal',20),y+1,x+1,reverseattr);
- fastwrite(center(' ',20),y+2,x+1,reverseattr);
- fastwrite(center('(c) Copyright 1988',20),y+3,x+1,reverseattr);
- fastwrite(center(' Kenny D. Walker',20),y+4,x+1,reverseattr);
- fastwrite(center('All Rights Reserved',20),y+5,x+1,reverseattr);
- fastwrite(center(' ',20),y+6,x+1,reverseattr);
- fastwrite(center('Press A Key',20),y+7,x+1,reverseattr);
- chr1:=scankey;
- chr1:='a';
- end;
- else
- write(BELL); {sound for invalid key press}
- end;{case}
- until chr1 in [CR,ESC]; {can only exit with these two key values}
- date:=tempdate;
- restorecursorstate(oldxy,scanlines); {restore cursor}
- end;
-
-
- begin {calendar}
- if(other_attr<>0) then {check attribute values}
- normalattr:=other_attr;
- if(current_attr<>0) then
- intenseattr:=current_attr;
- if(select_attr<>0) then
- reverseattr:=select_attr;
-
- if(x<1) then {check display coordinates}
- x:=1;
- if(y<1) then
- y:=1;
- if(x>58) then
- x:=58;
- if(flag) then begin
- if(y>8) then
- y:=8;
- end
- else
- if(y>16) then
- y:=16;
-
- with todaysdate do
- getdate(year,month,day,dayofweek); {get current system date}
-
- if(not(month in [1..12])) then {check VAR parameter values}
- month:=1;
- if(month=2) then begin
- if(leap_year(year)) then begin
- if(day>29) then
- day:=29;
- end
- else
- if(day>28) then
- day:=28;
- end
- else
- case month of
- 1,3,5,7,8,10,12:if(day>31) then
- day:=31;
- 2,4,6,8,11:if(day>30) then
- day:=30;
- end;
- if(year<1) then
- year:=1;
- if(day<1) then
- day:=1;
-
- date.year:=year;
- date.month:=month;
- date.day:=day;
- if flag then begin {if wanting to use}
- if not savewindow(x,y,x+21,y+16,true,buffer) then; {selection mode, save}
- framewindow(x,y+9,x+21,y+16,7,15,'Calendar Keys'); {current screen, and}
- fastwrite('Prev Next',y+10,x+9,7); {draw instruction }
- fastwrite('Day '+chr(27)+' '+chr(26),y+11,x+3,7); {screen}
- fastwrite('Month '+chr(24)+' '+chr(25),y+12,x+3,7);
- fastwrite('Year PgUp PgDn',y+13,x+3,7);
- fastwrite(chr(17)+chr(196)+chr(217)+' Accept',y+14,x+6,7);
- fastwrite('Esc Cancel',y+15,x+6,7);
- changeattribute(8,y+11,x+10,15);
- changeattribute(8,y+12,x+10,15);
- changeattribute(10,y+13,x+9,15);
- changeattribute(3,y+14,x+6,15);
- changeattribute(3,y+15,x+6,15);
- getcalkey(date); {get the date}
- restorewindow(x,y,x+21,y+16,true,buffer); {restore screen}
- end
- else {if not using selection mode, then just draw}
- stuffcal; {calendar}
-
- year:=date.year; {return selected date in VAR parameters}
- month:=date.month;
- day:=date.day;
- end;
-
- begin
- end.