619 lines
23 KiB
Plaintext
619 lines
23 KiB
Plaintext
_STRUCTURED PROGRAMMING COLUMN_
|
||
by Jeff Duntemann
|
||
|
||
[LISTING ONE]
|
||
|
||
{ Calendar unit demo program }
|
||
{ Jeff Duntemann -- 2/3/89 }
|
||
|
||
|
||
PROGRAM CalTest;
|
||
|
||
|
||
USES DOS,Crt, { Standard Borland units }
|
||
Screens, { Given in DDJ 4/89 }
|
||
Calendar; { Given in DDJ 6/89 }
|
||
|
||
CONST
|
||
YellowOnBlue = $1E; { Text attribute; yellow chars on blue background }
|
||
CalX = 25;
|
||
CalY = 5;
|
||
|
||
|
||
VAR
|
||
MyScreen : ScreenPtr; { Type exported by Screens unit }
|
||
WorkScreen : Screen; { Type exported by Screens unit }
|
||
Ch : Char;
|
||
Quit : Boolean;
|
||
ShowFor : DateTime; { Type exported by DOS unit }
|
||
I : Word; { Dummy; picks up dayofweek field in GetDate }
|
||
|
||
|
||
BEGIN
|
||
MyScreen := @WorkScreen; { Create a pointer to WorkScreen }
|
||
InitScreen(MyScreen,True);
|
||
ClrScreen(MyScreen,ClearAtom); { Clear the entire screen }
|
||
Quit := False;
|
||
|
||
WITH ShowFor DO { Start with clock date }
|
||
GetDate(Year,Month,Day,I);
|
||
|
||
ShowCalendar(MyScreen,ShowFor,CalX,CalY,YellowOnBlue);
|
||
|
||
REPEAT { Until Enter is pressed: }
|
||
IF Keypressed THEN { If a keystroke is detected }
|
||
BEGIN
|
||
Ch := ReadKey; { Pick up the keystroke }
|
||
IF Ord(Ch) = 0 THEN { See if it's an extended keystroke }
|
||
BEGIN
|
||
Ch := ReadKey; { If so, pick up scan code }
|
||
CASE Ord(Ch) OF { and parse it }
|
||
72 : Pan(MyScreen,Up,1); { Up arrow }
|
||
80 : Pan(MyScreen,Down,1); { Down arrow }
|
||
75 : BEGIN { Left arrow; "down time" }
|
||
WITH ShowFor DO
|
||
IF Month = 1 THEN
|
||
BEGIN
|
||
Month := 12;
|
||
Dec(Year)
|
||
END
|
||
ELSE Dec(Month);
|
||
ShowCalendar(MyScreen,ShowFor,CalX,CalY,YellowOnBlue);
|
||
END;
|
||
77 : BEGIN { Right arrow; "up time" }
|
||
WITH ShowFor DO
|
||
IF Month = 12 THEN
|
||
BEGIN
|
||
Month := 1;
|
||
Inc(Year)
|
||
END
|
||
ELSE Inc(Month);
|
||
ShowCalendar(MyScreen,ShowFor,CalX,CalY,YellowOnBlue);
|
||
END;
|
||
END { CASE }
|
||
END
|
||
ELSE { If it's an ordinary keystroke, test for quit: }
|
||
IF Ch = Chr(13) THEN Quit := True
|
||
END;
|
||
UNTIL Quit;
|
||
ClrScreen(MyScreen,ClearAtom) { All this stuff's exported by Screens }
|
||
END.
|
||
|
||
|
||
[LISTING TWO]
|
||
|
||
{--------------------------------------------------------------}
|
||
{ CALENDAR }
|
||
{ }
|
||
{ Text calendar for virtual screen platform }
|
||
{ }
|
||
{ by Jeff Duntemann KI6RA }
|
||
{ Turbo Pascal 5.0 }
|
||
{ Last modified 2/3/89 }
|
||
{--------------------------------------------------------------}
|
||
|
||
UNIT Calendar;
|
||
|
||
INTERFACE
|
||
|
||
USES DOS, { Standard Borland unit }
|
||
TextInfo, { Given in DDJ 3/89 }
|
||
Screens, { Given in DDJ 4/89 }
|
||
CalCalc; { Given in DDJ 6/89 courtesy Michael Covington }
|
||
|
||
TYPE
|
||
DaysOfWeek = (Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
|
||
Months = (January,February,March,April,May,June,July,
|
||
August,September,October,November,December);
|
||
|
||
|
||
PROCEDURE ShowCalendar(Target : ScreenPtr;
|
||
ShowFor : DateTime;
|
||
CalX,CalY : Integer;
|
||
Attribute : Byte);
|
||
|
||
|
||
IMPLEMENTATION
|
||
|
||
TYPE
|
||
String10 = STRING[10];
|
||
|
||
CONST
|
||
MonthNames : ARRAY[January..December] OF String10 =
|
||
('January','February', 'March','April','May','June','July',
|
||
'August', 'September','October','November','December');
|
||
Days : ARRAY[January..December] OF Integer =
|
||
(31,28,31,30,31,30,31,31,30,31,30,31);
|
||
|
||
{$L CALBLKS}
|
||
{$F+} PROCEDURE CalFrame; EXTERNAL;
|
||
PROCEDURE Caldata; EXTERNAL;
|
||
{$F-}
|
||
|
||
{$L BLKBLAST}
|
||
{$F+}
|
||
PROCEDURE BlkBlast(ScreenEnd,StoreEnd : Pointer;
|
||
ScreenX,ScreenY : Integer;
|
||
ULX,ULY : Integer;
|
||
Width,Height : Integer;
|
||
Attribute : Byte;
|
||
DeadLines : Integer;
|
||
TopStop : Integer);
|
||
EXTERNAL;
|
||
{$F-}
|
||
|
||
|
||
|
||
FUNCTION IsLeapYear(Year : Integer) : Boolean;
|
||
|
||
{ Works from 1901 - 2199 }
|
||
|
||
BEGIN
|
||
IsLeapYear := False;
|
||
IF (Year MOD 4) = 0 THEN IsLeapYear := True
|
||
END;
|
||
|
||
|
||
|
||
|
||
PROCEDURE FrameCalendar(Target : ScreenPtr;
|
||
CalX,CalY : Integer;
|
||
Attribute : Byte;
|
||
StartDay : DaysOfWeek;
|
||
DayCount : Integer);
|
||
|
||
TYPE
|
||
PointerMath = RECORD
|
||
CASE BOOLEAN OF
|
||
True : (APointer : Pointer);
|
||
False : (OfsWord : Word;
|
||
SegWord : Word)
|
||
END;
|
||
|
||
VAR
|
||
DataPtr : Pointer;
|
||
FudgeIt : PointerMath;
|
||
DayInset : Word;
|
||
DayTopStop : Word;
|
||
|
||
BEGIN
|
||
{ DayInset allows is to specify which day of the week the first of the }
|
||
{ month falls. It's an offset into the block containing day figures }
|
||
DayInset := (7-Ord(StartDay))*4;
|
||
{ DayTopStop allows us to specify how many days to show in the month. }
|
||
DayTopStop := 28+(DayCount*4)-DayInset;
|
||
BlkBlast(Target,@CalFrame, { Display the calendar frame }
|
||
VisibleX,VisibleY, { Genned screen size from TextInfo unit }
|
||
CalX,CalY, { Show at specified coordinates }
|
||
29,17, { Size of calendar frame block }
|
||
Attribute, { Attribute to use for calendar frame }
|
||
0, { No interspersed empty lines }
|
||
0); { No topstop; show the whole thing. }
|
||
|
||
WITH FudgeIt DO { FudgeIt is a free union allowing pointer arithmetic }
|
||
BEGIN
|
||
APointer := @CalData; { Create the pointer to the days block }
|
||
OfsWord := OfsWord+DayInset; { Offset into block for start day }
|
||
|
||
BlkBlast(Target,APointer, { Blast the day block over the }
|
||
VisibleX,VisibleY, { calendar frame }
|
||
CalX+1,CalY+5, { Pos. of days relative to frame }
|
||
28,6, { Size of day block }
|
||
Attribute, { Show days in same color as frame }
|
||
1, { Insert 1 line between block lines }
|
||
DayTopStop) { Set limit on number of chars to }
|
||
END { be copied from block to control }
|
||
END; { how many days shown for a month }
|
||
|
||
|
||
|
||
|
||
PROCEDURE ShowCalendar(Target : ScreenPtr;
|
||
ShowFor : DateTime;
|
||
CalX,CalY : Integer;
|
||
Attribute : Byte);
|
||
|
||
CONST
|
||
NameOffset : ARRAY[January..December] OF Integer =
|
||
(8,8,10,10,11,10,10,9,7,8,8,8);
|
||
|
||
VAR
|
||
StartDay : DaysOfWeek;
|
||
TargetMonth : Months;
|
||
TargetDay : Real;
|
||
DaysInMonth : Integer;
|
||
|
||
BEGIN
|
||
{ First figure day number since 1980: }
|
||
WITH ShowFor DO TargetDay := DayNumber(Year,Month,1);
|
||
{ Then use the day number to calculate day-of-the-week: }
|
||
StartDay := DaysOfWeek(WeekDay(TargetDay)-1);
|
||
TargetMonth := Months(ShowFor.Month-1);
|
||
DaysInMonth := Days[TargetMonth];
|
||
{ Test and/or adjust for leap year: }
|
||
IF TargetMonth = February THEN
|
||
IF IsLeapYear(ShowFor.Year) THEN DaysInMonth := 29;
|
||
{ Now draw the frame on the virtual screen! }
|
||
FrameCalendar(Target,
|
||
CalX,CalY,
|
||
Attribute,
|
||
StartDay,
|
||
DaysInMonth);
|
||
{ Add the month name and year atop the frame: }
|
||
GotoXY(Target,CalX+NameOffset[TargetMonth],CalY+1);
|
||
WriteTo(Target,MonthNames[TargetMonth]+' '+IntStr(ShowFor.Year,4));
|
||
END;
|
||
|
||
|
||
|
||
END.
|
||
|
||
[LISTING THREE]
|
||
|
||
UNIT CalCalc;
|
||
|
||
{ --- Calendrics --- }
|
||
|
||
{ Long-range calendrical package in standard Pascal }
|
||
{ Copyright 1985 Michael A. Covington }
|
||
|
||
INTERFACE
|
||
|
||
function daynumber(year,month,day:integer):real;
|
||
|
||
procedure caldate(date:real; var year,month,day:integer);
|
||
|
||
function weekday(date:real):integer;
|
||
|
||
function julian(date:real):real;
|
||
|
||
IMPLEMENTATION
|
||
|
||
|
||
function floor(x:real) : real;
|
||
{ Largest whole number not greater than x. }
|
||
{ Uses real data type to accommodate large numbers. }
|
||
begin
|
||
if (x < 0) and (frac(x) <> 0) then
|
||
floor := int(x) - 1.0
|
||
else
|
||
floor := int(x)
|
||
end;
|
||
|
||
|
||
|
||
function daynumber(year,month,day:integer):real;
|
||
{ Number of days elapsed since 1980 January 0 (1979 December 31). }
|
||
{ Note that the year should be given as (e.g.) 1985, not just 85. }
|
||
{ Switches from Julian to Gregorian calendar on Oct. 15, 1582. }
|
||
var
|
||
y,m: integer;
|
||
a,b,d: real;
|
||
begin
|
||
if year < 0 then y := year + 1
|
||
else y := year;
|
||
m := month;
|
||
if month < 3 then
|
||
begin
|
||
m := m + 12;
|
||
y := y - 1
|
||
end;
|
||
d := floor(365.25*y) + int(30.6001*(m+1)) + day - 723244.0;
|
||
if d < -145068.0 then
|
||
{ Julian calendar }
|
||
daynumber := d
|
||
else
|
||
{ Gregorian calendar }
|
||
begin
|
||
a := floor(y/100.0);
|
||
b := 2 - a + floor(a/4.0);
|
||
daynumber := d + b
|
||
end
|
||
end;
|
||
|
||
procedure caldate(date:real; var year,month,day:integer);
|
||
{ Inverse of DAYNUMBER; given date, finds year, month, and day. }
|
||
{ Uses real arithmetic because numbers are too big for integers. }
|
||
var
|
||
a,aa,b,c,d,e,z: real;
|
||
y: integer;
|
||
begin
|
||
z := int(date + 2444239.0);
|
||
if date < -145078.0 then
|
||
{ Julian calendar }
|
||
a := z
|
||
else
|
||
{ Gregorian calendar }
|
||
begin
|
||
aa := floor((z-1867216.25)/36524.25);
|
||
a := z + 1 + aa - floor(aa/4.0)
|
||
end;
|
||
b := a + 1524.0;
|
||
c := int((b-122.1)/365.25);
|
||
d := int(365.25*c);
|
||
e := int((b-d)/30.6001);
|
||
day := trunc(b - d - int(30.6001*e));
|
||
if e > 13.5 then month := trunc(e - 13.0)
|
||
else month := trunc(e - 1.0);
|
||
if month > 2 then y := trunc(c - 4716.0)
|
||
else y := trunc(c - 4715.0);
|
||
if y < 1 then year := y - 1
|
||
else year := y
|
||
end;
|
||
|
||
function weekday(date:real):integer;
|
||
{ Given day number as used in the above routines, }
|
||
{ finds day of week (1 = Sunday, 2 = Monday, etc.). }
|
||
var
|
||
dd: real;
|
||
begin
|
||
dd := date;
|
||
while dd > 28000.0 do dd:=dd-28000.0;
|
||
while dd < 0 do dd:=dd+28000.0;
|
||
weekday := ((trunc(dd) + 1) mod 7) + 1
|
||
end;
|
||
|
||
function julian(date:real):real;
|
||
{ Converts result of DAYNUMBER into a Julian date. }
|
||
begin
|
||
julian := date + 2444238.5
|
||
end;
|
||
|
||
END. { CalCalc }
|
||
|
||
[LISTING FOUR]
|
||
|
||
;===========================================================================
|
||
;
|
||
; B L K B L A S T - Blast 2D character pattern and attributes into memory
|
||
;
|
||
;===========================================================================
|
||
;
|
||
; by Jeff Duntemann 3 February 1989
|
||
;
|
||
; BLKBLAST is written to be called from Turbo Pascal 5.0 using the EXTERNAL
|
||
; machine-code procedure convention.
|
||
;
|
||
; This version is written to be used with the SCREENS.PAS virtual screens
|
||
; unit for Turbo Pascal 5.0. See DDJ for 4/89.
|
||
;
|
||
; Declare the procedure itself as external using this declaration:
|
||
;
|
||
; PROCEDURE BlkBlast(ScreenEnd,StoreEnd : Pointer;
|
||
; ScreenX,ScreenY : Integer;
|
||
; ULX,ULY : Integer;
|
||
; Width,Height : Integer;
|
||
; Attribute : Byte;
|
||
; DeadLines : Integer;
|
||
; TopStop : Integer);
|
||
; EXTERNAL;
|
||
;
|
||
; The idea is to store a video pattern as an assembly-language external or
|
||
; as a typed constant, and then blast it into memory so that it isn't seen
|
||
; to "flow" down from top to bottom, even on 8088 machines.
|
||
;
|
||
; During the blast itself, the attribute byte passed in the Attribute
|
||
; parameter is written to the screen along with the character information
|
||
; pointed to by the source pointer. In effect, this means we do a byte-sized
|
||
; read from the source character data, but a word-sized write to the screen.
|
||
;
|
||
; The DeadLines parm specifies how many screen lines to skip between lines of
|
||
; the pattern. The skipped lines are not disturbed. TopStop provides a byte
|
||
; count that is the maximum number of bytes to blast in from the pattern.
|
||
; If a 0 is passed in TopStop, the value is ignored.
|
||
;
|
||
; To reassemble BLKBLAST:
|
||
;
|
||
; Assemble this file with MASM or TASM: "C>MASM BLKBLAST;"
|
||
; (The semicolon is unnecessary with TASM.)
|
||
;
|
||
; No need to relink; Turbo Pascal uses the .OBJ only.
|
||
;
|
||
;========================
|
||
;
|
||
; STACK PROTOCOL
|
||
;
|
||
; This creature puts lots of things on the stack. Study closely:
|
||
;
|
||
|
||
ONSTACK STRUC
|
||
OldBP DW ? ;Caller's BP value saved on the stack
|
||
RetAddr DD ? ;Full 32-bit return address. (This is a FAR proc!)
|
||
TopStop DW ? ;Maximum number of chars to be copied from block pattern
|
||
DeadLns DW ? ;Number of lines of dead space to insert between blasted lines
|
||
Attr DW ? ;Attribute to be added to blasted pattern
|
||
BHeight DW ? ;Height of block to be blasted to the screen
|
||
BWidth DW ? ;Width of block to be blasted to the screen
|
||
ULY DW ? ;Y coordinate of upper left corner of the block
|
||
ULX DW ? ;X coordinate of the upper left corner of the block
|
||
YSize DW ? ;Genned max Y dimension of current visible screen
|
||
XSize DW ? ;Genned max X dimension of current visible screen
|
||
Block DD ? ;32-bit pointer to block pattern somewhere in memory
|
||
Screen DD ? ;32-bit pointer to an array of pointers to screen lines
|
||
ENDMRK DB ? ;Dummy field for stack struct size calculation
|
||
ONSTACK ENDS
|
||
|
||
|
||
CODE SEGMENT PUBLIC
|
||
ASSUME CS:CODE
|
||
PUBLIC BlkBlast
|
||
|
||
BlkBlast PROC FAR
|
||
PUSH BP ;Save Turbo Pascal's BP value
|
||
MOV BP,SP ;SP becomes new value in BP
|
||
PUSH DS ;Save Turbo Pascal's DS value
|
||
|
||
;-------------------------------------------------------------------------
|
||
; If a zero is passed in TopStop, then we fill the TopStop field in the
|
||
; struct with the full size of the block, calculated by multiplying
|
||
; BWidth times BHeight. This makes it unnecessary for the caller to
|
||
; pass the full size of the block in the TopStop parameter if topstopping
|
||
; is not required.
|
||
;-------------------------------------------------------------------------
|
||
CMP [BP].TopStop,0 ; See if zero was passed in TopStop
|
||
JNZ GetPtrs ; If not, skip this operation
|
||
MOV AX,[BP].BWidth ; Load block width into AX
|
||
MUL [BP].BHeight ; Multiply by block height, to AX
|
||
MOV [BP].TopStop,AX ; Put the product back into TopStop
|
||
|
||
;-------------------------------------------------------------------------
|
||
; The first important task is to get the first pointer in the ShowPtrs
|
||
; array into ES:DI. This involved two LES operations: The first to get
|
||
; the pointer to ShowPtrs (field Screen in the stack struct) into ES:DI,
|
||
; the second to use ES:DI to get the first ShowPtrs pointer into ES:DI.
|
||
; Remembering that ShowPtrs is an *array* of pointers, the next task is
|
||
; to index DI into the array by multiplying the top line number (ULY)
|
||
; less one (because we're one-based) by 4 using SHL and then adding that
|
||
; index to DI:
|
||
;-------------------------------------------------------------------------
|
||
GetPtrs: LES DI,[BP].Screen ; Address of ShowPtrs array in ES:DI
|
||
MOV CX,[BP].ULY ; Load line address of block dest. to CX
|
||
DEC CX ; Subtract 1 'cause we're one-based
|
||
SHL CX,1 ; Multiply CX by 4 by shifting it left...
|
||
SHL CX,1 ; ...twice.
|
||
ADD DI,CX ; Add the resulting index to DI.
|
||
|
||
MOV BX,DI ; Copy offset of ShowPtrs into BX
|
||
MOV DX,ES ; Copy segment of ShowPtrs into DX
|
||
LES DI,ES:[DI] ; Load first line pointer into ES:DI
|
||
|
||
;-------------------------------------------------------------------------
|
||
; The inset from the left margin of the block's destination is given in
|
||
; struct field ULX. It's one-based, so it has to be decremented by one,
|
||
; then multiplied by two using SHL since each character atom is two bytes
|
||
; in size. The value in the stack frame is adjusted (it's not a VAR parm,
|
||
; so that's safe) and then read from the frame at the start of each line
|
||
; blast and added to the line offset in DI.
|
||
;-------------------------------------------------------------------------
|
||
DEC [BP].ULX ; Subtract 1 'cause we're one-based
|
||
SHL [BP].ULX,1 ; Multiply by 2 to cover word moves
|
||
ADD DI,[BP].ULX ; And add the adjustment to DI
|
||
|
||
;-------------------------------------------------------------------------
|
||
; One additional adjustment must be made before we start: The Deadspace
|
||
; parm puts 1 or more lines of empty space between each line of the block
|
||
; that we're blasting onto the screen. This value is passed in the
|
||
; DEADLNS field in the struct. It's passed as the number of lines to skip,
|
||
; but we have to multiply it by 4 so that it becomes an index into the
|
||
; ShowPtrs array, each element of which is four bytes in size. Like ULX,
|
||
; the value is adjusted in the stack frame and added to the stored offset
|
||
; value we keep in DX each time we set up the pointer in ES:DI to blast the
|
||
; next line.
|
||
;-------------------------------------------------------------------------
|
||
SHL [BP].DEADLNS,1 ; Shift dead space line count by 1...
|
||
SHL [BP].DEADLNS,1 ; ...and again to multiply by 4
|
||
|
||
LDS SI,[BP].Block ; Load pointer to block into DS:SI
|
||
|
||
;-------------------------------------------------------------------------
|
||
; This is the loop that does the actual block-blasting. Two counters are
|
||
; kept, and share CX by being separate values in CH and CL. After
|
||
; each line blast, both pointers are adjusted and the counters swapped,
|
||
; the LOOP counter decremented and tested, and then the counters swapped
|
||
; again.
|
||
;-------------------------------------------------------------------------
|
||
MovEm: MOV CX,[BP].BWidth ; Load atom counter into CH
|
||
MOV AH,BYTE PTR [BP].Attr ; Load attribute into AH
|
||
DoChar: LODSB ; Load char from block storage into AL
|
||
STOSW ; Store AX into ES:DI; increment DI by 2
|
||
LOOP DoChar ; Go back for next char if CX > 0
|
||
|
||
;-------------------------------------------------------------------------
|
||
; Immediately after a line is blasted from block to screen, we adjust.
|
||
; First we move the pointer in ES:DI to the next pointer in the
|
||
; Turbo Pascal ShowPtrs array. Note that the source pointer does NOT
|
||
; need adjusting. After blasting through one line of the source block,
|
||
; SI is left pointing at the first character of the next line of the
|
||
; source block. Also note the addition of the deadspace adjustment to
|
||
; BX *before* BX is copied into DI, so that the adjustment will be
|
||
; retained through all the rest of the lines moved. Finally, we subtract
|
||
; the number of characters in a line from TopStop, and see if there are
|
||
; fewer counts left in TopStop than there are characters in a block line.
|
||
; If so, we force BWidth to the number of remaining characters, and
|
||
; BHeight to one, so that we will blast only one remaining (short) line.
|
||
;-------------------------------------------------------------------------
|
||
MOV ES,DX ; Copy ShowPtrs segment from DX into ES
|
||
ADD BX,4 ; Bounce BX to next pointer offset
|
||
ADD BX,[BP].DeadLns ; Add deadspace adjustment to BX
|
||
LES DI,ES:[BX] ; Load next pointer into ES:DI
|
||
ADD DI,[BP].ULX ; Add adjustment for X offset into screen
|
||
|
||
MOV AX,[BP].TopStop ; Load current TopStop value into AX
|
||
SUB AX,[BP].BWidth ; Subtract BWidth from TopSTop value
|
||
JBE GoHome ; If TopStop is <= zero, we're done.
|
||
MOV [BP].TopStop,AX ; Put TopStop value back in stack struct
|
||
CMP AX,[BP].BWidth ; Compare what remains in TopStop to BWidth
|
||
JAE MovEm ; If at least one BWidth remains, loop again
|
||
MOV [BP].BWidth,AX ; Otherwise, replace BWidth with remainder
|
||
JMP MovEm ; and jump to last go-thru
|
||
|
||
;-------------------------------------------------------------------------
|
||
; When the outer loop is finished, the work is done. Restore registers
|
||
; and return to Turbo Pascal.
|
||
;-------------------------------------------------------------------------
|
||
|
||
GoHome: POP DS ; Restore Turbo Pascal's
|
||
MOV SP,BP ; Restore Turbo Pascal's stack pointer...
|
||
POP BP ; ...and BP
|
||
RET ENDMRK-RETADDR-4 ; Clean up stack and return as FAR proc!
|
||
; (would be ENDMRK-RETADDR-2 for NEAR...)
|
||
|
||
BlkBlast ENDP
|
||
CODE ENDS
|
||
END
|
||
|
||
|
||
|
||
[LISTING FIVE]
|
||
|
||
|
||
TITLE CalBlks -- External calendar pattern blocks
|
||
|
||
; By Jeff Duntemann -- TASM 1.0 -- Last modified 3/1/89
|
||
;
|
||
; For use with CALENDAR.PAS and BLKBLAST.ASM as described in DDJ 6/89
|
||
|
||
CODE SEGMENT WORD
|
||
ASSUME CS:CODE
|
||
|
||
|
||
CalFrame PROC FAR
|
||
PUBLIC CalFrame
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
|
||
DB '<27> <20>'
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ'
|
||
DB '<27>Sun<75>Mon<6F>Tue<75>Wed<65>Thu<68>Fri<72>Sat<61>'
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ'
|
||
DB '<27> <20> <20> <20> <20> <20> <20> <20>'
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ'
|
||
DB '<27> <20> <20> <20> <20> <20> <20> <20>'
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ'
|
||
DB '<27> <20> <20> <20> <20> <20> <20> <20>'
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ'
|
||
DB '<27> <20> <20> <20> <20> <20> <20> <20>'
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ'
|
||
DB '<27> <20> <20> <20> <20> <20> <20> <20>'
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ'
|
||
DB '<27> <20> <20> <20> <20> <20> <20> <20>'
|
||
DB '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;'
|
||
Calframe ENDP
|
||
|
||
CalData PROC FAR
|
||
PUBLIC CalData
|
||
DB ' <20> <20> <20> <20> <20> <20> <20>'
|
||
DB ' 1<> 2<> 3<> 4<> 5<> 6<> 7<>'
|
||
DB ' 8<> 9<> 10<31> 11<31> 12<31> 13<31> 14<31>'
|
||
DB ' 15<31> 16<31> 17<31> 18<31> 19<31> 20<32> 21<32>'
|
||
DB ' 22<32> 23<32> 24<32> 25<32> 26<32> 27<32> 28<32>'
|
||
DB ' 29<32> 30<33> 31<33> <20> <20> <20> <20>'
|
||
DB ' <20> <20> <20> <20> <20> <20> <20>'
|
||
DB ' <20> <20> <20> <20> <20> <20> <20>'
|
||
|
||
CalData ENDP
|
||
|
||
|
||
CODE ENDS
|
||
|
||
END
|
||
|