cal-4.0/0042755000076400007640000000000007416652456012273 5ustar cbagwellcbagwellcal-4.0/cal.html0100644000076400007640000003254307416503266013714 0ustar cbagwellcbagwell CAL

CAL  -  display a calendar
(substitute unix "cal" command)

by Alex Matulich, Unicorn Research Corporation
Version 4.0


Contents:



NAME

cal - displays a calendar

SYNOPSIS

cal [options] [[num_month] year]
cal [options] [word_month] [year]

DESCRIPTION

By default, cal will display a calendar for the current month with the current day marked. By specifing certain arguments, cal will display a calendar for a whole year or a specified month and year.

The transition from the Julian to Gregorian calendar is assumed to have occured in 1752 on the 3rd of September. Ten days following that date were eliminated by the reformation, so the calendar for that month is a bit unusual.

If displaying a calendar in the single-month format, cal will look for a date file. If found, cal will read the file, looking for special date descriptions for that month which will be displayed to the right of the calendar. By default, up to 24 appointments may be displayed per month. If the current date happens to fall on one of these special dates, it will be flagged by an asterisk. If there is room, appointments for the next month may also be displayed with some limitations (currently, special dates such as the 3rd Thursday of will not be calculated for next month).

cal can also optionally use colors when displaying the calendar. It will not display colors any time the calendar is not directly displaying on the console. This is generally the desired behavior when your redirecting cal's output to another program or a file.

ARGUMENTS

A verbally-specified month may be entered without specifying a year in the argument list; however, a single numerical argument will be interpreted as a year. Only the first 3 characters of the month name are significant for a verbally-specified month. NOTE: The command "cal 10" refers to 10 AD, not October, and not 1910.

The available options are:

--3[months]
Display previous/current/next month together. This option will be ignored when displaying a full year.
--a[ppts]
Maximum number of appointments to display. Minimum is 8, maximum is 50, default is 24.
--col[or-file]=filename
Read color definitions from `filename' (default color filename depends on operating system).
--con[tinue]=n
Display the next n successive months starting with the month specified.
--d[ata-file]=filename
Read appointments from `filename' (default appointment data filename depends on operating system). You may use -d up to 8 times in a commandline to specify multiple data file names.
--e[urope]
Use European format (first weekday is Monday).
--f[uture]
If current month is displayed, then show only future appointments from the date file, not appointments that are past. This allows room for other descriptions with future dates to be displayed. As time progresses through the month, old descriptions are discarded and newer ones are used. The --future switch affects only the display for the current month, and not other months.
--j[ulian]
Display Julian dates (days one-based, numbered from January 1.
--m[onday]
Display Monday as the first day of the week (same as --europe)
--noc[olor]
Inhibit the use of colors.
--nod[ata]
Do not try to read any appointment data file.
--p[ause]
Pause before exiting and prompt for a keystroke.
--th[ismonth]
Disable display of next month appointments; show only current month's.
--to[day]
Show only today's appointments.
--u[se-color]
Allow the use of colors.
--y[ear]
Display a calendar for the current year.

There is an optional environment variable that can be used by cal if found. If CALOPT is set then cal will read it and use any valid command line options found. This allows any commonly used switches to be set in your environment and always used (e.g. --europe). Cal will produce its usage screen when run if any invalid options are set in this variable.

COMMAND EXAMPLES

cal -f -d=my_dates
display the current month and future appointments defined in file 'my_dates'
cal 1996
display the entire year of 1996
cal 9 1752
display the month of September 1752
cal sep 1752
same as above
cal January
display January of the current year
cal help
help message displayed for unrecognized arguments

DATE FILES

cal will search for a date file called cal.dat in the directory it was executed from. If not found it will search in the users $HOME directory for a file called .cal.dat. If still not found, it will look for a global cal.dat in a system wide directory. To find out where this location is you can run cal --help which will display the location.

The special date descriptions specified in the date file are single lines, formatted as follows:

YYYY MM DD NW xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

where

YYYY is the year,
MM is the month (01 - 12),
DD is the day (00 if the NW field is used),
NW is the weekday-of-month code (00 if the DD field is used)
xxxx is the description; it will be truncated as necessary to fit

The data MUST occupy the character fields as shown. If YYYY is specified as -999, the month and day are assumed to be annual events such as holidays, and the description will be displayed for any year. If MM is specified as -9, the day is assumed to be a monthly event for the specified year. In the weekday-of-month code NW, N signifies on which weekday W the special date occurs. For example, 31 indicates the third sunday. Values of W range from 1 to 7, for Sunday to Saturday, respectively. A value of 9 for N indicates "last" as in 95 for "last thursday."

If ALL of the fields contain a positive number and the year is at least 1970, then the description is assumed to be periodic, starting at the given date, with the period in days specified in NW (e.g. 1995 01 06 14 will display the description every 2nd Friday using 6 January 1995 as the base date). The base date does not get displayed.

You can display birthdays and anniversaries by putting the year of birth (or other special event) inside brackets or braces, in the description. This number is converted to the number of years since the year you indicate and the brackets or braces are removed from the output. If braces {} are used the number will have an ordinal suffix, as in 21st, 32nd, 43rd, 54th, etc. If the number in brackets or braces is greater than the current year, the number will be displayed unchanged. Example: "Alex's {1961} birthday" will display as "Alex's 34th birthday" (if the current year is 1995). If you need to include brackets or braces in your output then you can escape them by prefixing it with a '\'. Example: "Alex's \{1961\} birthday" will be displayed as "Alex's {1961} birthday".

NOTE: If cal is invoked with the --europe or --monday switch, then the W values 1-7 denote Monday(1) to Sunday(7) rather than Sunday(1) to Saturday(7).

A line in cal.dat must start with -999 or a 4-digit number to be considered as data. The data lines may be in any order. All these appointments will be displayed in chronological order, regardless of the ordering in the appointment data file.

If cal was compiled with the reminder support then call will also search for the files dates and .dates in the same places as for the caldat equivalents. The dates file is used by the reminder(1) program and is an alternate, less-powerful format for specifying descriptions. A file in this format cannot be specified with the --data-file= option.

The reminder format consists of text lines of length < screen width in the following format:

DDDDDDDD:N:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:yyyyyy:S

where

DDDDDDDD
is the date in one of the following formats:
M/D/Y
an event occurring on a specific day (year can be two or four digits, but must be two for backward compatibility with reminder)
M/D
an event occurring every year
D
an event occurring every month
DDD
an event occurring every week (day of the week is 'Sun', 'Mon', etc.)
N
is the number of days notice of the event to give the user (ignored by cal)
xxxxx
the event description
yyyyy
an optional receptor of the event (e.g. Mr. Jones)
S
status flag, either N for normal event or D for a deleted (not displayed) event

Blank lines are ignored. A line otherwise not in the above format is assume to specify a file name from which to read more events. The file is searched for in the usual places.

COLOR ATTRIBUTES

cal will search for a color definition file called cal.col in the directory it was executed from. If not found it will search in the users $HOME directory for a file called .cal.col. If still not found, it will look for a global cal.col in a system wide directory. To find out where this location is you can run cal --help which will display the location.

Users may override the default colors used when displaying calendars. This may be done by creating a color definition file.

Example of a color definition file:

15 02   video colors for month name
01 03   video colors for weekday header
07 01   video colors for normal calendar days
13 01   video colors for sundays
14 02   video colors for current day
07 06   bkgd for yearly calendar (space between months)
11 00   video colors for special day descriptions
12 08   video colors for * indicating descr.=today

Color definitions must appear as above, as a two-character field for the foreground color, followed by a space, folowed by a two-character field for the background color. The color definitions must start on the first line, and must not contain blank lines. Comments may appear after the second field, provided that the total line length does not exceed 80 characters.

Possible colors:
0   black
1   blue
2   green
3   cyan
4   red
5   violet
6   orange
7   light gray
 
8   dark gray
9   bright blue
10   bright green
11   bright cyan
12   bright red
13   bright violet
14   yellow
15   white

Specifying a background color from 8 to 15 will result in a background color of 0 to 7, with flashing text.

FILES

cal.dat
Date file. Can be located in the current directory or the directory in which cal is run from.
cal.col
Color definition file. Can be located in the current directory or the directory in which cal is run from.
$HOME/.cal.dat
unix local date file.
$HOME/.cal.col
unix local color file.
$HOME/.dates
Date file used with unix reminder program and can be used with cal.

BUGS

All known bugs fixed in version 4.0.

WHERE TO GET CAL

The latest version of cal is available from http://unicorn.us.com/pub/cal40.zip

AUTHOR

Alex Matulich - alex@unicorn.us.com

...with enhancements and modifications by other contributors.

- © 1993-2002 by Unicorn Research Corporation
Inspired by an Amiga program by Gary L. Brant.


SEE ALSO

date(1), reminder(1), rs(1)

cal-4.0/cal.exe0100644000076400007640000043303207416472341013526 0ustar cbagwellcbagwellMZ '`T stub.h generated from stub.asm by djasm, on Thu Dec 9 10:59:31 1999 The STUB.EXE stub loader is Copyright (C) 1993-1995 DJ Delorie. Permission granted to use for any purpose provided this copyright remains present and unmodified. This only applies to the stub, and not necessarily the whole program. $Id: stub.asm built 12/09/99 10:59:31 by djasm $ @(#) stub.asm built 12/09/99 10:59:31 by djasm go32stub, v 2.02T@CWSDPMI.EXE$`0!<smi  up9sÉǹJ!sω&,10&=PAu&=THu &==uG>Ou߯>!>!W1tn~^ uAr/ ut>6_>*6b>,t#,GtCf.EXEb=d!ù?!11ɡ=Lt=MZ  tډB!?!=u>Lafffffff+ff fKfOfff9sff1f t H!&(أ"11r11f16>1 ɃQɛ1I11 Yɓ1I11s=s1j f6f>fIf6 f>#f'7f>KfOf1fgf>!1fd.ff%f)f)f&f>"6>f6B:FBN>G?( u &; v Bf1ɋFf>"f"f)&f1gff&u<:t;AdtD*t\Fr4DCFuW*__dK!_r M!-(>ir X!gX!hX!X!Ü>irPSXh0!Xg0![XLoad error: $: can't open$: not EXE$: not COFF (Check for viruses)$no DPMI - Get csdpmi*b.zip$no DOS memory$need DOS 3$can't switch mode$no DPMI selectors$no DPMI memory$L~4  XL .textX4 .data   @.bss44LQ_u%=|fd51۹v 1ff 1sL!fDcf fɃfɓ1P_t+ff1ff1ff1Ct%P_Q_t{ ^f1sL!fNf^fVp f¹l1f 41%4%4 4 1f1ft f 41@Q= 19tff14Qf 6Qd$4ˉf-PNd8QdPX1VSFۍ+fPFf+ f9t;f9/f)Gf"VhS{LuPUMf         D@P1 Pd^P6M D@P1 Pl^PM  D@P1 P@YPL  )@P1 P\^PL\^ f=  j1 Pd^PLj1 Pl^PrL j1 P@YPTLf5!ftP1 P ! )ÍKftRҍA@YPKf=  97f !ftP1 P5 ! )ЍPftvB@YPKhL]hL]jDh] 0 0u DYKjKR^fHlffXf@ f h^Cf`^fHY h"I}Y }t}Nf=!uWf!f !fPPCf ~ ff!f !f}^f=!tf h^P D@Pj S!J h^PP  TRډff)R h$S|i hGt&h^PP8fCf ~u V*DAuBDA:-f=!tf U BPSAV  D@Pj S IVV  TRډff)R h$SlhhF &VP/fCf ~yvM AP@u ÃVЉуtzt8(t1@8(t,@8(t'@utttu߃@@)ЃvCGf /ǃ!PVhjVU BPi ủfu'Dž}u>M Q*DAuu F@DAty:-utR?ff!f !f|^PPCf ~ ff!f !f} &DžT&Džf=!t;h,hfh-Ah h-jP(E!P_k[^_]UUf=!t!8^f!]ÍvUf!]UfEf=!tfEMfEf9ME AE9~ЋufEfEff= uEPEPsfEf}}fE1f;uf fL"ftFfEf9f HfEF!duH9uONj[f9}Rh6 ffƒ !PffR9OP0OS6M[^_]\/ect/cal/U WVSE PEPOǃ[LY=LYz؉ڃtzt80t1@80t,@80t'@utttu߃@@)=(SVHM؉ڃtzt8"t/B8"t*B8"t%Buttt uBB)ڃtzt8(t1@8(t,@8(t'@utttu߃@@+ETw{؉ڃtzt80t1@80t,@80t'@utttu߃@@x/thDVmMEPV]ME PVMǃ DMDBfBfڋuttt uBB)ڃtzt8(t1@8(t,@8(t'@utttu߃@@+EwEPSLE PSLǍ[^_]Ð cal 4.0 - Display a monthly or yearly calendar, with optional appointments. Usages: cal [options] [[1|2|3|...|12] year] cal [options] [jan|feb|mar|...|dec] [year] Options: --3[months] Display prev/current/next month --a[ppts]=n Display maximum of n (8-50) appointments (24) --con[tinue]=n Display successive months n times after the first --d[ata-file]=file Load appointments from `file' (default: /etc/cal/cal.dat) --e[urope] European format (first day is Monday) --f[uture] Show only future appointments on current month --j[uian] Display Julian dates (days numbered from 1 January --m[onday] Display Monday as first day of week (same as --europe) --nod[ata] Ignore appointment descriptions file --p[ause] Pause for keystroke before exiting --th[ismonth] Show only current month appointments --to[day] Show only today's appointments on current month --y[ear] Display a calendar for the current year --u[se-color] Allow use of colors --noc[olor] Inhibit the use of colors --col[or-file]=file Load color definitions from `file' (default: cal.col) (c) 1992-2002 A. Matulich, Unicorn Research Corporation http://www.unicorn.us.com Uh,hF?h,hH? h,hH?h,hH? h,h0K?h,hH? h,hKo?h,hK]?]É'UWVS1}1GÃ}&1ҊGЃ Ä|E [^_]ÍvUWVS11}1ҊGЃ ƃ|w@t ƋE 0[^_]ÐUWVSE ptVUZM NES">UEEE EEB t(Ã;t<}uWVEPP;uEPEPURUBPEPURUB EEeȉB[^_]U WVS(4 &[t;u SE;r;Cs 1<s19s+[ t& >P9Us P 9Ur y9r1e[^_]ehUWVSE] QP)ЉE EUֹ1t EQt)}ֹ1t tEx zt13}tzt8"t/B8"t*B8"t%Buttt uBBUBuuFC CCPR ƒC PRE1 CB8zuEPRUЍe[^_]ÍvU1WVS]uUC@t?F!} ?E,tU ?ED\/$SuVPTTT`TpTTTuVuVTUU USUqUpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVpVUV0V 1C1fEPScÃEPSTMN UËE MD\E  EPS"ËEU D\EPSÃEPSMËE D\‹E\&EPSÃEPSËEU fBXEB"EPSËEM fAXEPSrËEU BjtV9u U BpM ϋApƃPk;u M E\0UBEvgEPSËEU B KEPSÃEPSMN UËE MD\E ى +>e؉[^_]ÍvUEU B(4BB BB(4]ÍvUS]j8PS]]ÍvUEU BB (4BBB(4]ÍvUS]j7PS]]ÍvU(4SE=(4t*9CuC;t C P9S{u=]]ÐUEPP9]ÐUWVSEPlt ]SlRhu1x1xEfEҋEll|B)ƒr9hs"jMQShPh9rE쉽h8zu'tPR`thhllpBp9hs5;Ew0pWMQShPDh9s U9pv֋} E H[^_]ÍvUWVSE1@E%?)ĉe;}spvӍUGE&U JE U@EtE֋ @I)ȅ|UE};}r11;]sEtCG;}rUe؉Z[^_]UcP,4Ѓt h!FcPRJ]387No 80387 detected. Warning: Coprocessor not present and DPMI setup failed! If application attempts floating operations system may hang! EMU387emu387.dxeUVSuh(Z Ãt/1"Ife<u~ ~ v~ ~ ]US]SK~(Vf.bcF*F~nF^NV ZF XfF(F$ffF,ff.fn0fV2cF$Shp>EVPt C$)C$\Fe[^]Uhp4EjPp4]UWVSME |Ë$s9~)v}} +E9} Ћ5 s9~+E)MUE U9E ׋5s9~(E)MUE U9Q1u+Uʋ})׉}E<9u'Uʋ})׉}E<9uE s9)A뇍vQvI1u+Uʋ})׉}E<9u'Uʋ})׉}E<9usE 88xe[^_]ÍvUWVUS}EHuExXEUE U9r6u,E}u{EU9C~EsvMyUE.‹E]E.[؉])؉EU )+EU)yMÀQx vÀEQųىډ )ЉEGE+EU)ىډ)ЉEG+EىE)}tAM$Iˉʉ)ЉEE+E)OyOEPh1u/Q։u)‰UE9u+Q։u)‰UE9uUGO؉WӉr9r!vG+‰]U]BEW9\~UG E eBG(W [^_]SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec%.3s %.3s%3d %02d:%02d:%02d %d vUUBlPPBPBPB PB@لPB@ĄPhh4=K츠4]UEPhP]ÉUWVSM] u;9|1}-;ω;y#H߉EU)‰3މ) e[^_]ÐUSM UAZ)É؅u@AZ)É؅u2A Z )É؅u$AZ)É؅uAZ)É؅u)‰Ћ]]ÐUWVSu>=vj} u4NvE92Pum19]~fڋE92PtO2LU+0LMUQMQEM PэEPMQDuE9Eu EEC9^NGM9s#MMMQMQEM PыMEe[^_]ÍvUWVUSz ~B EMPU QRMQuUz p>} u4KuM9v}UB 9P19u}MA 9PtpULL)Uz EJ PUM RQURV}uJMLL)NjU)z J F9srSEU9U8e[^_]ÐU,WVS}ԋu jhMQà M A9~MAjhQZMQ) Qu.)MQjhQ'ËM )qt))Ãu}u vMQ#eȉ[^_]ÍvU@WVS] C1$CC @CC= /t'C`uuCP9tK K@ uE1C!u/S%t% ~HCC vSReE~HCC1vS%P6EǃtM1AM>t%SuǀKCC [^_]ÐUSU Mˈt BAu؋]]ÐEvUWVS]uH5~~hF=~t v5~KCKul{teC)Eƅ~W{1uC C t /tEPVWCP҃uVWCPBE Ey)DžCtCcC1e[^_]ÍvUWVS}wEE$E -tZ0}u9rNÉ@9r3)BJA;tBD - -U1t@u(J(Jt)EEEv9Ew 9E$K[u}@}(J(Jvu93C}9; -tBExuƋ1tBu}Wuv(J -A(J})BJA;tBD -K[VB,}}WCÃu1b9$-uuރ5$-%C4}u߃=$-uEDDL Ce[^_]ÉUWVSUPB$ZBdCCu~)ljHމ9 -u -yu@tBuS{(J(Jtv9u@ P@uAˉDTust9 -u -yutBuQy(J(Jtv9u@ P@uCD{u1t vBuS{(J Ce[^_]ÐUWVSuE uP62~9w$PÃtWVS VL؍e[^_]UVW}u M}A_^EÉUSUM Ӏ;t vB:uABu؋]]ÐUWVS} 1ۃ}OAƅ ]G<+t t +uEuu!1xu/%ytu 'vzt"*]Call frame traceback EIPs: 0x 0x UWVSj$0t%f-~e1҈¿ BAwz =0Q 8YcMXj hѕjjc@ P`1v9]v;3t5[jhj\jS4O~c9Xw~sjhj*e[^_]Alignment CheckCoprocessor ErrorPage faultGeneral Protection FaultStack FaultSegment Not PresentInvalid TSSCoprocessor overrunDouble FaultCoprocessor not availableInvalid OpcodeBounds CheckOverflowBreakpointNMIDebugDivision by Zero: sel= invalid base= limit=USE] jPj8jhȗj jS taEPSftj hϗj =jhٗj jEPsS=jhj} $jSRjhja ]]Floating Point exceptionControl-Break PressedINTR key PressedQUIT key PressedRaisedException at eip=, error=, x87 status= eax= ebx= ecx= edx= esi= edi= ebp= esp= program=csdsesfsgsssApp stack: [..] Exceptn stack: [] vUWVSc]p8=~ t#If-~e8@-t `@-aw H-1Ƀuu $uyuŘ zu֘u*t jhfj hj jVTʉȃtzt80t1@80t,@80t'@utttu߃@@)PQjP jhj? t0cff9B(u!B9Bw=~r98Yv j@ vjc@ Pyujhj j(vw1-t(c1fX4tjhj jSV=!uj h j j:PWjhjf jcP7jh jI jc@Pjh&j( jc@Pjh,j (jc@ Pjh2j jc@Pjh8j (jc@Pjh>j jc@PzjhEj (jc@PYj hKjk L_uU1:t @<uPRj04jhj2 cf@(%Phccf@*% Phfcf@,%Phicf@.%Phlcf@0%Phocf@2% Phrj hujj0Q,QPUjhjg(j,QP7jhjIT_j@Pjhj)(jhT_jhj jhjc ff9B(ujUSUB=?w(u~ JE ؋]]ABRTFPE ILL SEGVTERMALRMHUP INT KILLPIPEQUITUSR1USR2NOFPTRAPExiting due to signal SIG0xvUVSujhj" w$jhjjZPjjhjjVjhje[^]Bad longjmp to __djgpp_exception_state--aborting UEwO=cuFTcP6tj2h0jGjvMc[H8MQctT9%PjBad signal handler, vUS]~@~ KJt;*uu-t=v=~vjhjSS1]]Cannot continue from exception, vUSc@8PfSVcz8v PRj hjSj]]ÉUS1ۍvEPS5u Q_tݰOPS5M ݰOM ݴOCv]Sju5hHPju5M HPM LPSj }5h@Pj 5M @PM DP =-t'hXPD-P5h\P5- ?hXPD-P5h\Ph`Ph@d5h\PD-PX5-fbft[btQf9TPu$9PPuhPPj4hbj4&hPPj4 b PP b TP]]ÐUVSEu ='ubb=*t 1bb1ff2ffuf t!؍e[^]UEPh']ÍvUEPh*o]ÍvU=~ th.h+h+h 1J@=?~bbf~fbd 4Q-bbEMEP4ME`1OM ‹MLE@vUfBHPFcfLPfDP=~ t @P`c&@PcD-EndRj#3EEldPj$2hbj 2hPPj2If-~e @-]ÉU1fb4U|t %b b]ÐU=<_t3@P9bufDPf9bu&EPm|$D$Gfg.fo0_OW ofG2wG<&G*&FG&FG&F G &FG(&FG$&FGfG,fW2c_^ύvUSVW]f1s f~1_^[]ÐVPfZZ>>u6>%??u(ٛ>t>f&.1^^ÍvUtmV.f=~~fe<:ufe%0%9Pu >\u ~\u1:EP1E@9Pt1ۅt.9.u =.uF..hót$%"vU<WVSh/jPs)ÃDžjjSb#PjjS8#QWS*S*| u99 D}ƅ[?t&Ph+t KC;u܍?t)"9.t1DAC9u]C>t< t< uF>u? tG< u9At#t[uCʃ9v< t< uJ9wBPV*1ɈM?$)ĉ=t tCF<=t< u< ?+uGW蟰<%{%u DžCPh!)C-$Ĵµµµµµµµµµµ|µµµµµµµµµµµµµµµµµµµµµµµµµµµµµµDž:Dž.Dž"DžDž DžC{{t9%t A9u鋍 CP8tAÉPhw'tt 1؊0t 1؊"t\u/t/u\F?utt t;FtCvCF;SQW$[^_]ÍvNo memory to gather arguments UEPujh0jj0]UU fmetBЉ)]US1];t QЃ ~QɃCЀ;u]]ÐUSjujjS詴؋]]UVSut P4Ft,1ۃ8tvPCF<uFPFt PMVe[^]ÍvUVS]jƉSFSjPe[^]ÐUVSu19~FP@C9FPwVqe[^]'"[?*...UWVS1]19] t9u01}uFC<'t<"u;C}u~w;\u/CPhиx$tE H9s}uFC?vt8PhӸF$ujh׸Sb$ u}t UCF>1E*,E+u0e[^_]UWVSMuME} 9st9sF1E*u9t[ËMCPEPMQWVEK EEM@P‹EPVRE uF9rMQ1ҋ]9U~FB[ 9Ue[^_]ÐUWVSMMM MMMEEÃtzt8#t/C8#t*C8#t%Cuttt uCCM+]MsMNjM9GO EMVSMQP M9MdMQ1ҋ}9U~vCt<:t<\tG(уPHPjQRGHF95D_Dž@P_u Wi<t WWN@D_PH_@tDWH_@Pd[^_]ÐUVS"9.t(. - 19}Ƌ C9|e[^]ÐUVS..tvCЉ؋P u - 19}Ɛ C9|.tС.tjj EP*UWVSuE*F%DCu-u E+uF}t}u0uxtXuNE}uE 0uE}t11uljU]fM*fEtvUtLt9M~8}| 9wu9M} EE]F뗍v}}}t~ }tۃ} t}tNE 0EU e[^_]US]S{~Sԥ]]ÐUh]ÍvU4EfEfEDEPj!RE%f=t1]ÍvUME UPR1f~Pf%QP*]ÉUSWfDcffЋ]} P=Pu f~fG f~fG.f~fG0fG fG.fG0f1s f~1 P_[]UME UPf%RPQ1f~Pj]ÉD$ .H .$ff.ff.ff.ff.USVWEE 8phXPH@.5..5..5..5.PUE@@8pXPH[fX X @_^[]ÍvUS]= /t3$`u)u$Pt $ $@ uZ1$!u/$%t4 $~H$$$vh$R $~H$$$1h$1Pi ]]ÉUWVS}u .tEPMQVW҃tEhvMQVWƒ Oj)PW ڃ /t,19}v<3tC9|~RVƒxЍe[^_]ÐUWVSuFt FF@ǁ~~u6u8~SFuF $FN ^ FFt}~-u,$t h$,t h,F 9F~FF=u~ ~Vu t.tVSFPFP҃ucSFPFP 1F!u/V%t.~*QjFP t+^j+PFPQ F9F ~FFFFtF}/uF @Ft $FNvF%Fe[^_]ÐU4WVS"9/t////}|~/C9ErawY/hǾ/=//)Pj/Puf/fEEgEPj!l/E Me[^_]ÍvUEP]U8WVSEjUERPj _tEPEPƃu~%PjEP` t E:vEAtEEqfEE衠~fEfEEPj!Eu1.1fEPÉ%PjEP~e[^_]ÉUxWVSu} uu]E,Sj!1EEU+EUF1ҊU1EUE*1ҊUEUSj!1E1ҊUEEEEEJEU1fE”EUP6t1V赱Q(ڸU]U)ЉI O|[^_1]ÍvUWVSE %E=1ɈMt%MQ0t~ 4M Mu 0/ MuEE }pƉU t~t1 ‰U }t1E PWMQà jE PMQ# Ãu[~\SMQitt'E @PMQ E tWMQÃE t}uMQQS7 E4 PSMQSE t jjS؍e[^_]ÍvU1ҋEM 8t 8u@8uu‰]U1V1S"] M9u17vAC11ҊT8Tt1"1ɊL1D%)ȍe[^]ÍvU EEAEEEU PEPRm‹E]ÍvUDWVS1M EMċ}PA E /tEPWMQEP҃uK'/UtWMQR }MQEPjMу E1fEP ~Ɖ~)vf-~~9s= ~Mv9s-MĊ uH9tEe CEeCF~9rϋEfE@fEf]䡠~f ~fEfMEPj!qE<1fE9J19Xe[^_]UWVSu Ft $FFu )~uSuO~SMǃ~u F $F+N ^ ~$u$PUtNFƒt8FMF^)} t9^ ~vۋEt M}M]Nj^~F )@F t /tEPSWFP҃uSWFPfE E~)DžFu FMFEe[^_]ÐUWVSM] UuBv1ҊS1T>))"v1p1DC8>uˊAtJu1e[^_]ÐUWVS}5.t%19^~DxtP׃C9^6u܍e[^_]É>v~Itu$UWVS..t2v1ҋC9}vDxtcB9|{uuՅujX޹Ãt<Cj 迹‹{Tօt j jVEPj!Eu1v~]ÐUEU 8t 8t @8ut1]UVSu] Mu!1Ҋ1C)‰C8uFtIu1e[^]UUM u1BA8t1)‰Љ]~vUEjP"]/dev/nullnulttyconenvvUWVSM 5~] ~+u Muu~ 赵f-~M9t y:u˃jhS BSйuEпuEvS<v<w1Ct-MtvB:uBKt Aue[^]ÐU4WVSE̋ufEDfEfu܋} Pj!EuA1f]t $߄}SfEDfEfu܍EPj!Et1fEP0~8u4PX/ڃ PVQ ؍e[^_]ÉUVS1MU v< tFACJue[^]ÍvUEUt M 8t@Ju1]ÉUj6…t1EB11]ÍvUWVS} u1t$VWURCЃ t  vu1e[^_]ÉU4E jtE fECqE vU CfUEP} uEfE䡠~fEfEEPj!Eu 1fEv1fEPx~]ÉUSE~jPK~t1]]ÍvU8VSEj؃}u~vUERPjƃ tEEPEfE$fu  fE܅tfElq8f=~u Sf=~v fElvE[f]f]f]ЋE fE䡠~fEEPj!Euj1fEP1fEv1fEP~e[^]ÐU8VSEj}u~vUERPjuà tEEPtfElqfEfEf]E09u uF1N,KِE$8-u 18uK;0u9uE$Kve[^_]U\WVSuEM F}-+F gfffʋ)Љ+ƒ~900K+ ~90ʀ0K9s0CF9r$0F~90ʀ0F[^_]NaNInfUS]U1} |rEtiEt-Ch1S؉ڃtzt8"t/B8"t*B8"t%Buttt uBBE)%P1fB%=t1:Bu:tOB t1S]]Ð vUUBw ]ÐUVSuPtVCPujRÃttzt80t1@80t,@80t'@utttu߃@@)@PCt!VP芌PPQ1vSe[^]*.*...vU<WVS}Mt9Q%P%PM QMQxuZYvM Y9 Qu.AM A QPt QPt  M Y4M jS QP v8:j}t^PQ PQu7Àt, &D PD C| uՋQM Q豊E Ãtzt8#t/C8#t*C8#t%Cuttt uCCQCQM9t0Q%P%PSQu1~QuC QPGQCQ%P%PjSMQyt QQ <1[^_]...UdWVS]u(Q%P%PjM CKjhS uDC<\t~P3M AAAPE Pb~M ffAj*Svu*j?SgÃuEfEqfEWj!)f]EM fAAA 1v~]fuEfESj!ENf}ࡠ~MfMfESj!¶EuM Qj,~P611fEP$~[^_]ÉUUBw 10Љ]ÉUDWVS]fEq=~j譟Wډ؃tzt80t1@80t,@80t'@utttu߃@@)@PS趵fEqfEfEfEfEfEEPj!趵Ef}q]u Sj P}tڊ< tCF)Ѓ!;uU v; uC)Ѓ;u; t#.U v< tCF)Ѓ ;u-vދ] v1PFCt +E ~e[^E _]ÐUtVSuu~tvj!fEOqfFfEfu~&=v~]fEfEfESj!]Eu\Ph>~PʹFFFPFP{FF 11fEP|~&fFfEqSj!dzEub,~]fEEfESj!藳~Ph"VVEOSj!zEuVj,~P1v1fEP~[^]ÉUE8t\t /t@8u1]UWVSM ]M;!1ɈMtC1C]1E0@Eu1;-uOKMtE]t@8U| M8M|}t 1MЊ98Tw1E8Tr%v8Ut}tM98DuC]r19ut؍e[^_]*?[\UWVS}Mu MG]?t9t#*tOY[\ A>%Fp\t/uEt[G*tu$}tV`%9E0\t/uIEtCV2ƃIMQVW! \t/u EFuF\t/u EEPPWǃ Eu6t0GPhutGu]OF8M\t/u<\tt'5M M ffffvvM fv5$QtYvSWQCx SM QW5x SQM Q!x ] )u[^_]U,EWVS}UEEUU EU}uF9v!}u 1NjEUEUU} ]M1[E9Ev]Ɖ]uUUu?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~wp``pP`@p0`p ` ` p ٢ gpfeyHiGY*I)9 ) ")` ` p`p`p` v!`"U#j$5%J&'*s'p) U)ޥp*7+p,T`-ip.6`/~Kp0`1gg2r`3GI4R`5'+62`7 889:;۞p?b@opA`BOpCda`D/vpEDC`FXpG$%`GtI`IVJ`K8LMNOwPQapRlS@pTLU pV,oWpX`XpYn`Zp[P`\]2`^_``ica~0bIEc^d)'e=fDpgg&phipjݚkplƷ`mpn`oqpp{`qZrf]`s:tF?`uv/[vpx=xRyz4{|Qp}~3pcpw`BpW`"p7` `j`˹L`h}Jk_,T|p`4^p?@p) `"p`p` ȳ`𝨕`|w`\q(7)/3&45Ma^fPy/  %&"       $ !  ##%%%%%%% %     !  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~.(null)Unnormal@@@ @ @4@p+ŝi@զIx@GA~QCǑF uuvHM]=];Z R`%u? ףp= ף?,eX?aw̫?[Mľ?9Eϔ?9'*?d|FU>:zc%C1<#2IZ9Wڥ2-64OSk%ޟݦ @@?. 3!3 3 3 3 3 3 3 3 3PT&2:FNV^i .file%gcrt0.ssel_buf4 # 5p Fp Ut zerov dz r`3   `$4a\exit# @ 4doR|YLFh.textT.data .bss4.eh_fram`3.file1gcal.cpp_opt!_q.93L".textp7.data  .bss(4.filezgframe.cLL @_add_lea _divide.eosf5 I  0 @ S i .eosf@w ]_NO_REGS _AREG _DREG _CREG _BREG _AD_REGS _Q_REGS _SIREG _DIREG        .eosfI  d_words_nregs_regno.eos f]  ] _.0fake l_quot_rem.eosff_div_t f_.1fake t_quot_rem.eosfn_ldiv_t n_size_t _wchar_t _.2fake ~_quot_rem.eosfx_lldiv_t x_dev_t _ino_t _mode_t _nlink_t _gid_t _off_t _pid_t _ssize_t _uid_t _fd_set  _fd_bits< .eos f _fd_set  _time_t    ( ; O h         & = U e x        . ?! U" g# $ % & ' ( ) * + , '- ;. N/ j0 1 2 3 4 5 @ A A *A .eosfA M [ k {             2 @ N \ j } .eosf 6        !  5  F  T  c  s                    (  = K ! ^ " q %  '  *  ,  .  /  1  2  3  4 2 5 D 6 ^ 7 k 8  9  :  ;  <  =  >  ?  @  A ! B 8 C J D ` E p F  G  H  I  J  K  L  M     6  R  k            %! 5! E! U! g! y! .eosf            / = K V b n z           ! " # "$ -% 8& D' O( Z) d* n+ x, - . / 0 1 2 3 4 5 6 7 8 9 : '; 4< A= N> [? h@ uA B C D E F G H I J K L M N +O 8P DQ PR \S hT tU V W X Y Z [ \ ] ^ _ `  a b %c 2d ?e Lf Yg fh si j k l m n o p q r s t u v )w 6x Cy Pz ^{ l| z} ~           " 0 > L Z h v        .eosf6      6 D S g x .eosf   .eosf     .eosf : H Y .eosfk    .eosf     .eosf+ E S b .eosfp      .eosf   .eosf  ) = J ] r      .eosf %   2 .eosfF ?]@ q          . A R i     - . / .eosf%, NC P [ j        .eosf? W 0 B Y n .eosfN  pf_cfa_eh_ptr 5H_cfa_regX Z _saved\2.eospfXp Xp_object s_pc_end X_count_nexth.eosfh _sword _uword _uaddr _saddr _ubyte   _length_CIE_id_version  2.eos fy  _length*5 .eosf_fde ? _eh_ptrIU a.eosfk t_sXppt.eostftLaE4.bfLe_buf _r  _buf_r.ef5Me8MaG4.bf8Me_buf _r  _buf_r.efMe _p _b2 _b4 _b8 .eosf _arrayX_count.eosf  _linear_erratic.eosf M!m 4.bfMe_v1 _v2  .efMeMh4.bfMe_accu _count  .efOeO/-4.bfOe .efOeO!c4.bfOe _accu  _beg_ptrQ _end_ptrQ _accu.efGPeHP! $4.bfHPe_ob h.efhQehQh*4.bfhQe _pc .efQe%Qa104.bfQe_f _c  _f_c.ef%Se7(SaY64&.bf(Se(_p _state  t_info _pcQ _p_info_pcQ.efVetIV!9B42.bfVes4_begin _ob  h_begin_obh.efVe`V!%H4:.bfVes<_begin _begin.efVerV!5N4F.bfVesH_begin _ob  h_begin_obh.efWe W!%T4N.bf WesP_begin _begin.efEWeHWaOZ4V.bfHWesX_begin _begin.efWeW!`4^.bfWes`_begin _begin.efWeWhXaf4g.bfWesk   Xp.efYe_objects(4hY!l4s.bfYes _linear _erratic  .efYe P".textL G.dataP".bss(4.filegnpxsetup.cYY_nofpsigY ,4.textYx .data`".bss,4.filegident.cp\p\.textp\.data`"t.bss04.filegcrt1.cp\p\! p\6 \E $]\ ]o P_| 04 _.textp\XF.data".bss04.filegfake aforcedb 5alimitFix b c @bstack_okads_limitb Sc d.text`).data".bss44.fileginfostrc.cdd.textd.data".bss44.filegct_lower.cdd.textd.data".bss44.filegatoi.cdd.textd.data$.bss44.fileggetenv.cdd.textdh.data$.bss44.filegstrtok.c@e@e_last.244.text@e.data$.bss44.filegstdout.cee.texte.data$ .bss84.filegfileno.cee.texte.data $.bss84.filegisatty.stub.textf.data $.bss84.file gint86.cff.textf<c.data $.bss84.filegstrncpy.cPjPj.textPj@.data $.bss84.file gcalloc.cjj.textj0.data $.bss84.file*gputs.cjj.textj,.data $.bss84.file4gfgets.cjj.textj.data $.bss84.file>gfclose.ckk.textk.data $.bss84.fileFgmemset.s.textl@.data $.bss84.filePgtime.cll.textl4.data $.bss84.filegctime.cmm )_GMTm m !_tm.41p4!p!Ą!ل!4!_tmcomp!H_time2H_time1.textm$y.data $.bss84.filegfputs.c@@.text@D.data*.bss(J.filegct_flags.c.text.data*.bss(J.filegstrcpy.c.text(.data,.bss(J.filegfake.text.data,.bss(J.filegstderr.cЍЍ.textЍ.data, .bss(J.filegstdin.c.text.data- .bss(J.filegfflush.c.text.data -.bss(J.filegmalloc.c_slop -"$-"(J.text.data -.bss(Jx.filegmemcpy.s.text.data0-.bssJ.filegstrcat.c  .text 0.data0-.bssJ.filegfopen.cPP.textPH.data0-.bssJ.filegabort.c_msg0-.text$.data0- .bssJ.filegdpmiexcp.cДД"@-,"D-_buf.48J_itoxД7" F"W"H-h"-s"""J"Z""-"O_npx_oriHP_kbd_ori@P"XP"\P"`P#PP #.textД.data@-d.bssJ.file"gfake.textt.data-.bssP.file*gd0e01.S.textp(.data-.bssP.file2gfake.textP.data-.bssP.file<g_write.c.text .data-.bssP.fileFgdxeload.c.text .data-.bssP.fileNgcntrl87.S.text(.data-.bssP.fileVgd0000.S.text$.data-.bssP.file^gd0008.S.text ,.data-.bssP.filefgd0400.S.textP8.data-.bssP.filengd0006.S.text,.data-.bssP.filevgmd.S.text,.data-.bssP.fileggetdos_v.c#-)#h..text.data-.bssP.filegosminor.c.text.datap..bssP.filegosmajor.c.text.datap..bssP.filegputenv.c8#p._ecountt._emaxx.F#|..textP8.datap..bssP.filegfrlist.cX#P.textP .data..bssPX.fileg_use_lfn.cPPl#.#.__lfnenv.#.#P.textPX,.data..bssP.filegc1loadef.c.texttE.data..bssP.filegc1args.c00#P#|_atohex_new_argз###\#ܸ#ع$$!$,$C$ؽ.text0t N.data..bssP.fileg_main.cU$..textD.data..bssP.filegerrno.c.text.data..bssP.filegexit.c.text .data..bssP.file gstrtol.c.texth.data..bssP.filegstdiohk.cm$.text8.data..bssP.filegisatty.c00.text0<.data..bssP.file(gdmp.cpp.textp,.data..bssP.file1gd0300_z.S$P.text.data..bssP.file;gdmg.c00.text0,.data..bssP.fileIgfakes_es.s_ds.s_fs.s_gs.$$.text` .data..bssP.fileSgputchar.c  .text .data..bssP.file]gread.c.text.data..bssP.fileggfilbuf.c.text.data/.bssP.filetgdosio.c$/$/_count/.text.data/ .bssP.file~gclose.cPP.textP.data /.bssP.filegremove.c``.text` .data /.bssP.fileggettimeo.c``.text`.data /.bssP.filegopen.cpp.textp.data /.bssP.filegstrrchr.c.text(.data /.bssP.filegstricmp.c00.text0d.data /.bssP.filegsprintf.c.text<.data /.bssP.filegwrite.c.text.data /.bssP.filegflsbuf.c``.text``.data0/.bssP.filegstrnicmp.c.textd.data0/.bssP.filegfwalk.c00.text0D.data0/.bssP.filegsbrk.stub.text.data0/.bssP.filegdjmd.s$$$big_move.text(.data0/.bssP.filegallocfil.c.text.data0/.bssP.file gfmode.cpp.textp.data0/.bssP.fileglseek.cpp.textp.data@/.bssP.filegdpmi_lsl.S.filegdpmi_lsl.s.text.data@/.bssP.file&gstat87.S.text0.data@/.bssP.file.gfake.text@X.data@/.bssP.file6gd0202.S.text,.data@/.bssP.file>gd0203.S.text,.data@/.bssP.fileFgd0204.S.text,.data@/.bssP.fileNgd0205.S.text0,.data@/.bssP.fileVgd0201.S.text`0.data@/.bssP.file^gd0304.S.text(.data@/.bssP.filefgd0200.S.text0.data@/.bssP.filengd0303.S.textD.data@/.bssP.filevgd0600.S.text@8.data@/.bssP.file~gclear87.S.text .data@/.bssP.filegfsext.c$@/_init_num_fdsP$P%l%D/)%.text'.data@/.bssP.filegdoserr2e.c00_mapP/.text0,.dataP/.bssP.fileg_open.c``.text` .dataP0.bssP.fileg_read.cPP.textP .dataP0.bssP.fileg_close.c@@.text@.dataP0.bssP.filegosflavor.c.text.dataP0.bssP.filegstrchr.c.text$.dataP0.bssP.filegstrncmp.c.text@.dataP0.bssP.filegstrcmp.c00.text00.dataP0.bssP.filegstdprn.c``.text`.dataP0 .bssP.filegstdaux.cpp.textp.datap0 .bssP.filegputpath.c5%.textX.data0.bssP.file gd_getdrv.c.text(.data0.bssP.filegct_upper.c.text.data0.bssP.filegc1pglob.c.text(.data1.bssP.file'gstrncat.c@@.text@@.data1.bssP.file1gsetmode.c.text.data1.bssP.file;gcrlf2nl.cPP.textP4.data1.bssP.fileEgmemchr.c.text .data1.bssP.filePgfse_open.c@%1.text|.data1.bssP.fileZg_chmod.c00.text0.data1.bssP.filedgfexistp.c.text4.data1.bssP.fileng_creat_n.c.text .data1.bssP.filexg_creat.c00.text0 .data1.bssP.filegdoprnt.c_decimal1_nan_p1K%1U%1_cvtl_pten1_ptennegd2_INVPREC3_PREC 3c%X_roundlo%8.text,.data1h.bssP.filegclose.stub.text@.data 3.bssP.filegdoserrno.cPP.textP.data 3.bssP.filegglob.cPPz%P_addh%P%Q%@%Q_glob2_pathbuf Q_slashQ%Q_flagsQ_use_lfnQ% _errfuncQ.textP p.data 3.bssP$.fileglconv.c  _ESTR 3_DSTR!3%$3.text  .data 34 .bss Q.filegputc.c  .text .data`3.bss Q.filegfake.text ,.data`3.bss Q.filegfindfirs.c.text .data`3.bss Q.fileglfnshort.c  % .text .data`3.bss Q.filegfindnext.c.text.data`3.bss Q.file gfnmatch.cpp%p &.textp.data`3.bss Q.file gfncase.cpp.textpD.data`3.bss Q.file gqsort.c_Cmpr Q&$Q_MyBase(Q!&,&_Swap(;&t.text8 .data`3.bss Q .file glibgcc2.c ] _div_t f_ldiv_t x_size_t _wchar_t _lldiv_t x_dev_t _ino_t _mode_t _nlink_t _gid_t _off_t _pid_t _ssize_t _uid_t _fd_set  _time_t G& ] U& _PQImode _QImode _PHImode _HImode _PSImode _SImode _PDImode _DImode _TImode _OImode _QFmode _HFmode _TQFmode _SFmode _DFmode _XFmode _TFmode _QCmode _HCmode _SCmode _DCmode _XCmode _TCmode _CQImode _CHImode _CSImode _CDImode _CTImode _COImode _BLKmode _CCmode _& k&! .eosf7 }& i & & & & _MODE_CC & & & .eosf]  _UQItype _SItype _USItype _DItype _UDItype _SFtype _DFtype _XFtype & & y _low_high.eosfs _.3fake  _s s _ll .eosfy _DIunion y  '/vr4 .bfe _u _v .efve'<.textx.data`3.bss,Q.file glibgcc2.c ] _div_t f_ldiv_t x_size_t _wchar_t _lldiv_t x_dev_t _ino_t _mode_t _nlink_t _gid_t _off_t _pid_t _ssize_t _uid_t _fd_set  _time_t  _UQItype _SItype _USItype _DItype _UDItype _SFtype _DFtype _XFtype & _DIunion y '/x4 .bfe_n _d _n.ef~e'<.text.data`3.bss,Q*'_europe !___exit_year!_putchar 6'@_sprintfQ'`__exitx','b_free8_strcat _strcmp0'@Y_videoDY'"'c'nd'( ( _thisdayHY1(~C(b_homedirLY_longjmpV(/k(4__flsbuf`x(__write_putc (,Q( _etext( (_LineWid ( (h1( /)5)~!)p.)!__readP8)~M)-_putsjY)0d)!n)Tb_regL]_buf!_linep]_int86f)~) _strncat@__open`) ))b)"edatad3__filbuf)b*`c%*`"___lseekp:*p0G*_mktimePY*~d*0_fputs@n*b_environ@_* *b*8^*8__days *~_isattyf*b*4* *|__doprnt8_sbrk+X^ +\^+g!_raise_strncpyPj%+`5+D_B+ZM+!Y+`^_atoid__stklen0Qd+`__chmod0_getargX_columns t+_memcpy+___sbrk_tzname)_continu!_memsetl+d+0+&_filenoe___tzsetx}+ $++d ,0end~_remove` ,!-,___modfl 9, _fflushetextG,.Z,0___main,,4Q,_strtol,P,,b___glob --~,- 7-d^A- L-_months!X-b-o-~!y-.__creat0_gmtimeT_julian!_fopenP-_callocj_timel__fmode0/- -d-ld-H_-_dayline!_ctimel-b.0.!#.$_realloc_memchr0. ;.T..j.`3_fixtab1~."..3.@d_getenvd.. .0.%/x/0/40_strchr line[0] -> [......LineWid (default 80).......] lln[0] line[1] -> [.................................] lln[1] line[2] -> [.................................] lln[2] ... [.................................] ... line[maxappts-1] -> [.................................] lln[maxappts-1] line_attr[0] -> [........LineWid (80).............] line_attr[1] -> [.................................] allocated line_attr[2] -> [.................................] only if ... [.................................] colors line_attr[maxappts-1] -> [.................................] are used mon_attr -> [......YEARWID (72)...........] wk_attr -> [......YEARWID (72)...........] day_attr -> [......YEARWID (72)...........] spclday_attr -> [....DAY_DESC (56).....] */ /* --- User Configuration ---------------------------------------------------*/ /* When compiling under DOS, define MSDOS. When compiling under OS/2 * define OS2. This allows certain DOS/OS/2'isms to be accessable. */ /* #define MSDOS */ /* #define OS2 */ /* To display the calendar in color, define USE_COLOR. Under MSDOS or * OS2, this will cause cal to access the video memory directly to * manipulate colors. Under unix, it will cause cal to use inline ANSI * escape codes for colors. */ #define USE_COLOR /* Most platforms have support for terminal drivers that understand * ANSI escape sequences to display colors. This includes most unix * terminals and DOS or OS/2 with the ANSI.SYS driver loaded. * Define USE_ANSI when ANSI color support is wanted under those platforms. * If left undefined here, it will be defined under unix if USE_COLOR * is defined above, and it will be undefined under OS2 and MSDOS. * By default OS2 and MSDOS will use video memory (USE_VIDEORAM) if * USE_COLOR is defined, unless USE_ANSI is defined here. */ /* #define USE_ANSI */ /* Some platforms do not have strncasecmp. For those, you can define * NEEDS_STRNCASECMP and use an internal version. */ /* #define NEEDS_STRNCASECMP */ /* --- End User Configuration -----------------------------------------------*/ /* Simply auto detect if we are in a unix style compile enviornment */ #if (defined(__unix__) || defined(UNIX)) && !defined(__DJGPP__) #undef MSDOS #undef OS2 #ifndef UNIX #define UNIX #endif #endif /* __unix__ */ #ifdef OS2 #undef MSDOS #undef UNIX #endif /* OS2 */ #ifdef MSDOS #undef OS/2 #undef UNIX #endif /* MSDOS */ #ifdef __DJGPP__ #ifndef MSDOS #define MSDOS #endif #undef UNIX #undef OS2 #define far #endif /* __DJGPP__ */ /* now that we know the operating system, set the color definitions */ #ifdef USE_COLOR #ifdef UNIX #undef USE_VIDEORAM #define USE_ANSI #endif #if defined(MSDOS) || defined(OS2) #ifdef USE_ANSI #undef USE_VIDEORAM #else #undef USE_ANSI #define USE_VIDEORAM #endif #endif #else #undef USE_ANSI #undef USE_VIDEORAM #endif /* USE_COLOR */ #define MAXFILES 8 /* maximum number of data file paths */ #define MAXAPPTS 50 /* maximum number of appointment description lines */ #define CAL_MAXPATH 1024 /* maximum size of path and filename strings */ #define MAXLINE 256 /* maximum length of lines in config files. */ /* Include files for accessing video memory */ #ifdef USE_VIDEORAM #ifdef OS2 #define INCL_SUB #include #else #include /* for int86() */ #endif /* OS2 */ #endif /* USE_VIDEORAM */ #include #include #include #include #include #include #ifndef UNIX #include /* for isatty() */ #endif #if defined(UNIX) || defined(DJGPP) #include #endif #ifdef HAVE_LOCALE_H #include #ifdef HAVE_LANGINFO_H #include #else #include /* libc4 only */ #endif #endif /* HAVE_LOCALE_H */ #ifndef max #define max(a,b) (((a)>(b))?(a):(b)) #endif /* max */ #ifdef USE_VIDEORAM #ifdef MSDOS #ifdef __DJGPP__ #include /* for _farpokeb() */ #include /* for _dos_ds */ #define MK_FP(seg,off) ((unsigned long)(seg)*16L+(off)) unsigned long video, tmpvideo; #else #ifndef MK_FP #define MK_FP(seg,off) (void far *)(((unsigned long)(seg)<<16)|(unsigned)(off)) #endif /* !MK_FP */ char far *video, far *tmpvideo; #endif /* __DJGPP__ */ union REGS reg; #endif /* MSDOS */ #endif /* USE_VIDEORAM */ #define THURSDAY 4 /* Used during reformation calculations */ #define SATURDAY 6 /* 1 Jan 1 was a Saturday */ #define FIRST_MISSING_DAY 639799 /* 3 Sep 1752 */ #define NUMBER_MISSING_DAYS 11 /* 11 day correction during reformation */ #define MONTHWID 24 #define J_MONTHWID 31 short LineWid = 80; /* Support for variable length widths */ short MonthWid = MONTHWID; /* Julian calendars are 31 characters */ short columns = 1; /* 2 or 3 columns in year view */ #define YEARWID (3*MonthWid-2) /* width of yearly calendar */ #define DAY_DESC (LineWid-MonthWid) /* width of special day descriptions */ #ifdef USE_COLOR /* define display attribute */ #define FG_BLACK 0x00 /* possibilities. */ #define FG_BLUE 0x01 #define FG_GREEN 0x02 #define FG_CYAN 0x03 #define FG_RED 0x04 #define FG_VIOLET 0x05 #define FG_ORANGE 0x06 #define FG_LTGRAY 0x07 #define FG_DKGRAY 0x08 #define FG_BRTBLUE 0x09 #define FG_BRTGREEN 0x0a #define FG_BRTCYAN 0x0b #define FG_BRTRED 0x0c #define FG_BRTVIOLET 0x0d #define FG_YELLOW 0x0e #define FG_WHITE 0x0f #define FG_FLASH 0x80 #define BG_BLACK 0x00 #define BG_BLUE 0x10 #define BG_GREEN 0x20 #define BG_CYAN 0x30 #define BG_RED 0x40 #define BG_VIOLET 0x50 #define BG_ORANGE 0x60 #define BG_WHITE 0x70 unsigned char dfmon_attr = FG_BLACK|BG_GREEN, /* video attribute for month name */ dfwk_attr = FG_BLUE|BG_CYAN, /* attribute for weekday header */ dfdy_attr = FG_BLACK|BG_WHITE, /* attribute for days */ dfsun_attr = FG_VIOLET|BG_WHITE, /* attribute for sundays */ dftoday_attr = FG_WHITE|BG_BLUE, /* attribute for current day */ dfbk_attr = FG_LTGRAY|BG_BLACK, /* year calendar background */ dfspday_attr = FG_BRTCYAN|BG_BLACK, /* special day description attr. */ dfspdfl_attr = FG_BRTRED|FG_FLASH; /* special day flasher */ #ifdef USE_ANSI char ansiterm_attr = FG_LTGRAY|FG_BLACK; /* ansiputs() terminator color */ #endif char *mon_attr, *wk_attr, *day_attr, *spclday_attr, *line_attr[MAXAPPTS]; /* By default we want colors under DOS and OS/2 but not UNIX */ #ifndef UNIX int crt = 1; #else int crt = 0; #endif char *color_file = "cal.col"; #endif /* USE_COLOR */ char *data_file = "cal.dat"; #define REMINDER_FILE "dates" short days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, thisday, thismonth, thisyear, discard_old = 0, prog_pause = 0, thismonth_only = 0, europe = 0, numfiles = 0, julian = 0, month3 = 0, year = 0, maxappts = 24, continu = 0; char *months[] = { "", "January ", "February", "March", "April", "May", "June", "July", "August " , "September", "October", "November", "December" }, USdays[] = " Su Mo Tu We Th Fr Sa ", Europedays[] = " Mo Tu We Th Fr Sa Su ", j_USdays[] = " Sun Mon Tue Wen Thu Fri Sat ", j_Europedays[] = " Mon Tue Wen Thu Fri Sat Sun ", *dayline = USdays, *filename[MAXFILES], homedir[CAL_MAXPATH], /* home directory from argv[0] or enviornment */ *line[MAXAPPTS], /* line buffer for body of calendar */ *buf = NULL; void addfilename(char *); void clearfilenames(void); void printmonth (short, short); short stryearlen(short); char *stryearcpy(char *, short); void fixtab(register short); short day_in_year(short, short, short); short day_in_week(short, short, short); void putattr(char *, register short); void setcolor(char); void ansiputs(char *, char *); short specialdays(short, short); short reminderdays(short, short); FILE *efopen(const char *, const char *); void usage(void); /* commandline argument list */ static struct arglist { char *opt; /* full argument string */ short needsvalue; /* 1=argument needs a value, 0=stand-alone */ } opt[] = { { "3months", 0 }, { "appts", 1 }, { "data-file", 1 }, { "europe", 0 }, { "future", 0 }, { "julian", 0 }, { "monday", 0 }, { "nodata", 0 }, { "pause", 0 }, { "thismonth", 0 }, { "today", 0 }, { "year", 0 }, { "continue", 0 }, #ifdef USE_COLOR { "use-color", 0 }, { "nocolor", 0 }, { "color-file", 1 }, #endif { NULL, 0 } }; /*=========================================================================== * GETARG * Return the index of the argument in the option array. val is set if the * argument needs a value. The passed arg to test does not have to be * exactly like one of the arguments in o; it just has to match one of them * enough to be uniquely identified. Any arg that is passed here should * begin with a '-' (or also a '/' if compiling for MSDOS or OS/2). *=========================================================================*/ int getarg(struct arglist *o, char *arg, char **val) { int len = -1, i = -1, found = -1; *val = NULL; while (*arg == '-' #if (defined(MSDOS) || defined(OS2)) || *arg == '/' #endif ) ++arg; while (arg[++len]) { arg[len] = tolower(arg[len]); if (arg[len] == '=') { arg[len] = '\0'; *val = &arg[len+1]; break; } } while (o[++i].opt) { if (!memcmp(o[i].opt, arg, len)) { if (found >= 0) return -1; found = i; } } if (found < 0) return -1; if (o[found].needsvalue && !(*val)) return -1; return found; } /*=========================================================================== * setopt * This function will set a global option based on the value passed in. * The value passed in must be a valid index into the options array. *=========================================================================*/ void setopt(int c, char *optarg) { switch (c) { case 0: month3 = 1; julian = 0; MonthWid = MONTHWID; break; case 1: maxappts = atoi(optarg); break; case 2: addfilename(optarg); break; case 3: europe = 1; break; case 4: discard_old = 1; break; /* show future dates only */ case 5: MonthWid = J_MONTHWID; julian = 1; month3 = 0; break; case 6: europe = 1; break; case 7: data_file = NULL; break; case 8: prog_pause = 1; break; case 9: thismonth_only = 1; break; /* show this month dates only */ case 10: discard_old = 2; break; /* show today's dates only */ case 11: year = 1; break; /* show this year calendar */ case 12: continu = atoi(optarg); /* display successive months */ if (continu > 0) maxappts = 8; break; #ifdef USE_COLOR case 13: crt = 1; break; case 14: crt = 0; break; case 15: color_file = optarg; break; #endif /* USE_COLOR */ } } #ifdef NEEDS_STRNCASECMP int strncasecmp(const char *s1, const char *s2, size_t n) { char ss1, ss2; for (; 0 < n; ++s1, ++s2, --n) { ss1 = tolower(*s1); ss2 = tolower(*s2); if (ss1 != ss2) return (((unsigned char)ss1 < (unsigned char)ss2) ? -1 : +1); else if (ss1 == '\0') return 0; } return (0); } #endif void text_init(void) { #ifdef HAVE_LOCALE_H int i, day; strcpy(dayline," "); for (i = 0; i < 7; i++) { if (europe) day = (i + 1) % 7; else day = i; #ifdef HAVE_LANGINFO_H strncat(dayline,nl_langinfo(ABDAY_1+day),julian ? 3 : 2); #else strncat(dayline,_time_info->abbrev_wkday[day],julian ? 3 : 2); #endif strcat(dayline, " "); } for (i = 1; i <= 12; i++) { #ifdef HAVE_LANGINFO_H months[i] = nl_langinfo(MON_1+i-1); #else months[i] = _time_info->full_month[i-1]; #endif } #else if (europe) dayline = julian ? j_Europedays : Europedays; else dayline = julian ? j_USdays : USdays; #endif } /* When printing only one month, we sometimes need to really display * 3 months at a time if the user requested this. */ void processmonth(short m, short y) { if (month3) { short prev_month, prev_year, next_month, next_year; if (m == 1) { prev_month = 12; prev_year = y - 1; } else { prev_month = m - 1; prev_year = y; } if (m == 12) { next_month = 1; next_year = y + 1; } else { next_month = m + 1; next_year = y; } columns = 3; fixtab (prev_year); printmonth (prev_month, prev_year); fixtab (y); printmonth (m, y); fixtab (next_year); printmonth (next_month, next_year); } else { fixtab (y); printmonth (m, y); } } /*=========================================================================== * MAIN * Process command line, allocate and initialize, etc. *=========================================================================*/ int main(int argc, char *argv[]) { short bufsiz, i, m, y; time_t t; struct tm *lt; int c; char *optarg; char *calopt, *s; int status=0; char str[MAXLINE]; #ifdef USE_COLOR FILE *colorfile; short fg[8], bg[8]; #endif /* USE_COLOR */ #ifdef HAVE_LOCALE_H setlocale(LC_ALL, ""); #endif clearfilenames(); /* First, set any options from the Env. Variable CALOPT */ calopt = getenv("CALOPT"); s = (calopt != NULL) ? s = strtok(calopt," ") : NULL; while (s != NULL) { if (*s != '-' #if (defined(MSDOS) || defined(OS2)) && *s != '/' #endif ) break; if ((c = getarg(opt, s, &optarg)) < 0) { usage(); status=1; /* Let user known program didn't run */ goto freestuff; } setopt(c, optarg); s = strtok(NULL," "); } /* Next, loop through command line options and set parameters */ for (i = 1; i < argc; ++i) { if (*argv[i] != '-' #if (defined(MSDOS) || defined(OS2)) && *argv[i] != '/' #endif ) break; if ((c = getarg(opt, argv[i], &optarg)) < 0) { usage(); status=1; /* Let user know program didn't run */ goto freestuff; } setopt(c, optarg); } #ifdef USE_COLOR /* If color is enabled, then double check to see if we are actually * displaying on a terminal. */ if (crt) crt = isatty(fileno(stdout)); #endif /* USE_COLOR */ if (maxappts < 8 || maxappts > MAXAPPTS) { usage(); status=2; /* Let user know failed because to many datafiles */ goto freestuff; } if (!numfiles && data_file) /* add default data file if none specified */ addfilename(data_file); /* make the argument list compatible with unix cal */ argc = argc - i + 1; for (m = 1; m < argc; ++m) argv[m] = argv[i++]; /* Find out the line width of terminal and store this value. */ #ifdef MSDOS reg.h.ah = 0x0f; /* function 0x0F of INT 0x10 - get display mode */ int86(0x10, ®, ®); LineWid = max(80, reg.h.ah); /* number of columns returned in AH */ /* The above should work for all displays. * The following can be used instead, but will work in EGA and VGA only:*/ /* Linewid = *((unsigned far *)0x004004a); */ #endif /* MSDOS */ /* find originating directory */ #ifndef UNIX strncpy(homedir,argv[0],CAL_MAXPATH-1); homedir[CAL_MAXPATH-1] = 0; /* Just to be safe */ i = strlen(homedir); while (i >= 0 && homedir[i] != '/' && homedir[i] != '\\' && homedir[i] != ':') homedir[i--] = '\0'; #else s = getenv("HOME"); strncpy(homedir,s,CAL_MAXPATH-1); homedir[CAL_MAXPATH-1] = 0; /* Just to be safe */ #endif /* UNIX */ /* allocate workspace buffer */ bufsiz = (maxappts)*LineWid + 2*DAY_DESC; #ifdef USE_COLOR /* adjust workspace for color enhancements */ bufsiz += (maxappts+2)*LineWid + YEARWID + (DAY_DESC+1); #endif /* USE_COLOR */ if ((buf = (char *)calloc(bufsiz,1)) == NULL) { puts("Memory overflow"); goto freestuff; } /* assign pointers into buf */ line[0] = buf; for (i = 1; i < maxappts; i++) line[i] = line[i-1] + LineWid; /* calendar body */ #ifdef USE_COLOR /* color attributes */ line_attr[0] = line[i-1] + LineWid; for (i = 1; i < maxappts; i++) line_attr[i] = line_attr[i-1] + LineWid; mon_attr = line_attr[i-1] + LineWid; wk_attr = mon_attr + YEARWID; day_attr = wk_attr + YEARWID; spclday_attr = day_attr + YEARWID; /* attempt to read in file of colors */ if (crt && (colorfile = efopen(color_file, "r")) != NULL) { for (i = 0; i < 8; i++) { if (fgets(str, sizeof(str), colorfile) == NULL) break; if ((fg[i] = atoi(str)) == (bg[i] = atoi(&str[3]))) break; if (fg[i] > 15 || bg[i] > 15) break; } fclose(colorfile); if (i >= 8) { dfmon_attr = fg[0] | (bg[0] << 4); dfwk_attr = fg[1] | (bg[1] << 4); dfdy_attr = fg[2] | (bg[2] << 4); dfsun_attr = fg[3] | (bg[3] << 4); dftoday_attr = fg[4] | (bg[4] << 4); dfbk_attr = fg[5] | (bg[5] << 4); dfspday_attr = fg[6] | (bg[6] << 4); dfspdfl_attr = fg[7] | (bg[7] << 4); } } /* initialize color attribute strings */ memset (mon_attr, dfmon_attr, YEARWID); memset (wk_attr, dfwk_attr, YEARWID); memset (day_attr, dfdy_attr, YEARWID); memset (spclday_attr, dfspday_attr, DAY_DESC+1); spclday_attr[0] = dfspdfl_attr; for (i = MonthWid-2; i <= MonthWid+MonthWid; i += MonthWid) { memset (&mon_attr[i], dfbk_attr, 2); memset (&wk_attr[i], dfbk_attr, 2); memset (&day_attr[i], dfbk_attr, 2); memset (&day_attr[i - MonthWid + 3 + (6 * (julian ? 4 : 3) * europe)], dfsun_attr, julian ? 3 : 2); } memset (&day_attr[i - MonthWid + 3 + (6 * (julian ? 4 : 3) *europe)], dfsun_attr, julian ? 3 : 2); #ifdef USE_ANSI ansiterm_attr = dfbk_attr; #endif #ifdef MSDOS #ifndef USE_ANSI /* Find the start of video memory under DOS. This is hardcoded * based on video mode. */ int86(0x11, ®, ®); /* read the equipment list into reg. */ video = MK_FP(((reg.x.ax & 48) == 48) ? 0xb000 : 0xb800, 0); #endif #endif /* MSDOS */ #endif /* USE_COLOR */ text_init(); /* now that all the setup is done, we can begin with the program proper */ t = time(NULL); lt = localtime(&t); thisyear = y = lt->tm_year + 1900; thismonth = m = lt->tm_mon + 1; thisday = lt->tm_mday; puts(""); /* first display a blank line */ switch (argc) { case 1: /* display current month if no arguments */ if (!year) while (continu-- >= 0) { processmonth(m, y); if (++m > 12) { m = 1; ++y; } } else { /* "columns" tells the printmonth function that we are multiplexing * 2 or more months together before printing. It implies that * appointments will not be displayed. */ columns = julian ? 2 : 3; fixtab (thisyear); memset(str, ' ', YEARWID); stryearcpy(str+(YEARWID/2)-(stryearlen(thisyear)/2), thisyear); fputs(str, stdout); puts("\n"); for (m = 1; m < 13; m++) printmonth (m, thisyear); } break; case 2: if (isdigit(argv[1][0]) || (isdigit(argv[1][1]) && argv[1][0] == '-')) { /* "columns" tells the printmonth function that we are * multiplexing 2 or more months together before printing. * It implies that appointments will not be displayed. */ columns = julian ? 2 : 3; fixtab (y = atoi(argv[1])); memset(str, ' ', YEARWID); stryearcpy(str+(YEARWID/2)-(stryearlen(y)/2), y); fputs(str, stdout); puts("\n"); for (m = 1; m < 13; m++) printmonth (m, y); break; } /* drop through to next case */ case 3: m = atoi(argv[1]); if (strlen(argv[1]) >= 3) { for (i = 1; i <= 12; i++) { strcpy(str, months[i]); if (!strncasecmp(argv[1], str, 3)) { m = i; break; } } } if (!m) { usage(); status=3; /* Let user know failed because invalid month */ break; } if (argc == 3) { if (isdigit(argv[2][0]) || (isdigit(argv[1][1]) && argv[2][0] == '-')) y = atoi(argv[2]); else { usage(); status=4; /* failed because invalid number parameters */ break; } } while (continu-- >= 0) { processmonth(m, y); if (++m > 12) { m = 1; ++y; } } break; default: usage(); status=4; /* failed because invalid number parameters */ } if (prog_pause) { fputs("\nPress the RETURN key to continue.", stderr); fflush(stdin); fgets(str, 3, stdin); } freestuff: free(buf); return (status); } /*=========================================================================== * addfilename() * append a file name into the list of files to read * name must be a static string *=========================================================================*/ void addfilename(char *name) { if (numfiles < MAXFILES && name) filename[numfiles++] = name; } /*=========================================================================== * clearfilenames() * empty the list of file names * NOTE: does not free() any entries *=========================================================================*/ void clearfilenames(void) { numfiles = 0; } /*=========================================================================== * printmonth() * either prints an entire month at a time or multiplexes * a month into a buffer, dumping the buffer after the third call. *=========================================================================*/ void printmonth(short m, short y) { register short first, last; register short index, p = 0; register char *ll; static short q = 0; short l, hilite = ((m == thismonth) && (y == thisyear)), num_appts = 0; if (columns > 1) { if (++q > columns) q = 1; p = MonthWid * (q - 1); /* character position of line in buffer */ if (q == 1) { memset(line[0], ' ', maxappts*LineWid); #ifdef USE_COLOR memcpy(line_attr[0], mon_attr, YEARWID); memcpy(line_attr[1], wk_attr, YEARWID); for (l = 2; l < 8; l++) memcpy(line_attr[l], day_attr, YEARWID); #endif /* USE_COLOR */ } memset(line[0]+p, ' ', MonthWid); memcpy(line[0]+p+((MonthWid-2)/2)-(strlen(months[m])/2), months[m], strlen(months[m])); memcpy(line[1]+p, dayline, MonthWid-2); } else { /* Not printing multiple columns */ /* initialize attribute buffers for month display */ #ifdef USE_COLOR for (l = 0; l < maxappts; l++) { if (l<1) memcpy(line_attr[l], mon_attr, MonthWid-1); else if (l<2) memcpy(line_attr[l], wk_attr, MonthWid-1); else if (l<8) memcpy(line_attr[l], day_attr, MonthWid-1); else memset(line_attr[l], 0, MonthWid-1); memcpy(&line_attr[l][MonthWid-1], spclday_attr, DAY_DESC+1); } memset(line[0], ' ', (maxappts)*LineWid); memcpy(line[0]+((MonthWid-2)/2)-((strlen(months[m])+1+stryearlen(y))/2), months[m], strlen(months[m])); stryearcpy(line[0]+((MonthWid-2)/2)-((strlen(months[m])+1 +stryearlen(y))/2)+strlen(months[m])+1, y); line[0][strlen(line[0])] = ' '; /* Remote NULL terminator */ memcpy(line[1]+p, dayline, MonthWid-2); #endif /* USE_COLOR */ } if (y == 1752 && m == 9) { /* special case Sep. 1752 */ line[2][p + 8 - 3*europe] = '1'; line[2][p + 11 - 3*europe] = '2'; first = 14; last = 16 + europe; index = 12 - 3 * europe; if (julian) index += 4; /* account for extra space for julian dates */ } else { /* day of week for first day of month */ short dow = day_in_week(1, m, y); first = 1; last = 7 - dow; index = 3 * dow; if (julian) index += dow; /* Add extra space for julian dates */ } for (l = 2; l < 8; ++l) { /* loop thru month one week per line */ ll = line[l] + p + 1; while (first <= last) { /* for each day in week encode day of month */ if (julian) { short diy = day_in_year(first, m, y); ll[index+2] = '0' + diy % 10; diy /= 10; if (diy) ll[index+1] = '0' + diy % 10; diy /= 10; if (diy) ll[index] = '0' + diy % 10; } else { if (first >= 10) ll[index] = '0' + first / 10; ll[index+1] = '0' + first % 10; } if (columns == 1 && hilite && first == thisday) { /* hilight today */ #ifdef USE_COLOR line_attr[l][index] = line_attr[l][index+1] = line_attr[l][index+2] = line_attr[l][index+3] = dftoday_attr; if (julian) line_attr[l][index+4] = dftoday_attr; #endif /* USE_COLOR */ #ifndef UNIX ll[index-1] = /* (crt) ? '\xde' : */ '<'; ll[index+(julian ? 3 : 2)] = /* (crt) ? '\xdd' : */ '>'; #else ll[index-1] = '<'; ll[index+(julian ? 3 : 2)] = '>'; #endif /* ! UNIX */ } index += 3; if (julian) index++; ++first; } last = (last + 7) > days[m] ? days[m] : last + 7; index = 0; } if (columns == 1) { num_appts = specialdays(m, y); #ifdef USE_REMINDER if (num_appts < 1) num_appts = reminderdays(m, y); #endif } /* end of not multi-column */ /* Force num_appts to be eight at minimum so that the day lines will * always be printed out (extra important for multi-column mode). */ num_appts = max(8, num_appts); for (l = 0; l < num_appts; l++) { if (columns == 1 || q == columns) { index = LineWid-1; ll = line[l]; while (index >= 1 && ll[index] == ' ') --index; if (q == columns) index = MonthWid*columns-3; /* leave one space after last day in week */ else if (index < MonthWid-1) index = MonthWid-1; ll[index+1] = '\0'; #ifdef USE_ANSI ansiputs(line[l],line_attr[l]); #else puts(ll); #ifdef USE_VIDEORAM putattr(line_attr[l], (columns > 1) ? MonthWid*columns-3 : LineWid-1); #endif /* USE_VIDEORAM */ #endif /* !USE_ANSI */ } } #ifdef USE_ANSI setcolor(0); #endif } short stryearlen(short year) { short yl = 0; short neg = (year < 0); if (neg) year = -year; do { yl++; year = year / 10; } while (year); if (neg) yl++; return yl; } char *stryearcpy(char *dest, short year) { char str[11], *p; short neg = (year < 0); p = str+10; *p = '\0'; if (neg) year = -year; do { --p; *p = '0' + year % 10; year = year / 10; } while (year); if (neg) *(--p) = '-'; strcpy(dest, p); return dest; } /* Before 1753, a leap year was simply every 4 years. After 1752, its * every 4 years unless it falls on a century. On century bounderies * its only counted every 4 centuries. */ #define is_leap_year(y) \ ((y) <= 1752 ? !((y) % 4) : \ (!((y) % 4) && ((y) % 100)) || !((y) % 400)) #define centuries_since_1700(y) \ ((y) > 1700 ? (y) / 100 - 17 : 0) #define quad_centuries_since_1700(y) \ ((y) > 1600 ? ((y) - 1600) / 400 : 0) #define leap_years_since_year_1(y) \ ((y) / 4 - centuries_since_1700(y) + quad_centuries_since_1700(y)) /*=========================================================================== * fixtab() - correct for leapyears. *=========================================================================*/ void fixtab(short y) { if (is_leap_year(y)) { days[2] = 29; } } /*=========================================================================== * day_in_year * return the 1 based day number within the specified year *============================================================================ */ short day_in_year(short d, short m, short y) { int i; for (i = 1; i < m; i++) { if (i == 2) d += (is_leap_year(y)) ? 29 : 28; else d += days[i]; } return d; } /*=========================================================================== * day_in_week * return the 0 based day number for any date from 1 Jan. 1 and * beyond. Assumes the Greogorian reformation eliminates 3 Sep. 1752 * through 13 Sep. 1752. Returns Thursday for all missing days. *=========================================================================*/ short day_in_week(short d, short m, short y) { long total_days; /* Calculate total number of days since year 1 for past years * ignoring leap years. Then add in leapyears. Then add in * total number of days that have pasted this year. */ total_days = (long)(y - 1) * 365 + leap_years_since_year_1(y - 1) + day_in_year(d, m, y); /* If day falls before 3 Sep. 1752, day of week we mod by 7 to see * how many weeks have passed. 1 Jan. 1 started on a saturday so * take acount of that by adding that number of days to count. */ if (total_days < FIRST_MISSING_DAY) return ((total_days - 1 + SATURDAY - europe) % 7); if (total_days >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) return (((total_days - 1 + SATURDAY - europe) - NUMBER_MISSING_DAYS) % 7); return (THURSDAY - europe); } #ifdef USE_VIDEORAM /*=========================================================================== * putattr() - MSDOS or OS/2 only * modify the video memory text attribute areas with the attributes passed * in attr of lengh len, starting at the current cursor location. *=========================================================================*/ void putattr(char *attr, register short len) /* write video attr. string */ { #ifdef OS2 USHORT row, col; int i; #endif /* OS2 */ if (!crt) return; #ifdef OS2 VioGetCurPos(&row, &col,0); --row; while (len) { /* minimize the number of Vio calls */ for (i = 1; i < len; i++) if (attr[i] != *attr) break; VioWrtNAttr((PBYTE) attr, i, row, col, 0); attr += i; col += i; len -= i; } #else /* if !OS2 */ reg.h.ah = 3; reg.h.bh = 0; int86(0x10, ®, ®); tmpvideo = video + ((LineWid << 1) * (reg.h.dh - 1) + reg.h.dl + 1); while (len--) { #ifdef __DJGPP__ _farpokeb(_dos_ds, tmpvideo, *(attr++)); #else *tmpvideo = *(attr++); #endif tmpvideo += 2; } #endif /* !OS2 */ } #endif /* USE_VIDEORAM */ #ifdef USE_ANSI /*=========================================================================== * ansiputs() * Puts a string to stdio in color as defined by line_attr. *=========================================================================*/ void ansiputs(char *l, char *a) { char prev_color; setcolor(*a); while (*l) { fputc(*l++,stdout); prev_color = *a++; if (prev_color != *a) setcolor(*a); } setcolor(ansiterm_attr); fputc('\n',stdout); } /*=========================================================================== * setcolor() * Set the color attributes to those passed in. *=========================================================================*/ void setcolor(char attr) { char command[256]; char dos2ansi[] = { 0, 4, 2, 6, 1, 5, 3, 7, 0, 4, 2, 6, 1, 5, 3, 7}; if (!crt) return; /* ANSI codes 0 = normal attributes (white one black) 1 = high intensity 5 = blinking 2 = Normal intensity 7 = reverse 4 = underlined 8 = invisible */ if (attr == 0) fputs("\033[0m",stdout); else { strcpy(command,"\033[0;"); if (attr&0x80) strcat(command,"5;"); if (attr&0x08) strcat(command,"1;"); sprintf(command,"%s3%d;4%dm",command,dos2ansi[attr&0x0F], dos2ansi[(attr&0x70)>>4]); fputs(command,stdout); } } #endif /* USE_ANSI */ /*============================================================================ * add_days() * function to return year, month, day of dates + n days * used in find periodic dates. * e.g. 1996 02 06 14 -- Payday! -- *==========================================================================*/ void add_days(short *y, short *m, short *d, short n) { short tmpfeb = days[2]; days[2] = is_leap_year(*y) ? 29 : 28; *d += n; while (*d > days[*m]) { *d -= days[*m]; if (++(*m) > 12) { ++(*y); days[2] = is_leap_year(*y) ? 29 : 28; *m = 1; } } days[2] = tmpfeb; /* restore original value */ } /* Returns the day for the given year and month that the nth day-of-week * occurs on. */ int nth_weekday(int y, int m, int n, int dow) { int first_dow; int day; int weeks_counted = 0; int days_in_month; if (m == 2) days_in_month = is_leap_year(y) ? 29 : 28; else days_in_month = days[m]; first_dow = day_in_week(1, m, y); /* If looking for something that occurs during first week, * calulate date now and return it. */ if (n == 1 && dow >= first_dow) { day = first_dow - dow + 1; return day; } /* For other cases, record the number of days left week */ day = 7 - first_dow; /* Record if we've detected a week that has dow in it */ if (dow >= first_dow) weeks_counted++; while (weeks_counted < n) { /* Check to see if next week will contain the dow we are looking * for. If not then get out of loop. */ if (day + dow + 1 > days_in_month) break; weeks_counted++; if (weeks_counted < n) day += 7; } /* Unless user asked to return the last occurance of that dow (9) * then check for error case and return that fact. */ if (n != 9 && weeks_counted != n) return -1; day += dow + 1; return day; } /* make space for a new item in the right spot & return pointer to it */ char *insertitem(char **lln, int maxentry, int dy) { short j,k,day; for (j = 0; j < maxentry; j++) /* insert in sorted order */ if (dy < (day = atoi(&lln[j][1]))) { k = maxentry; if (k == maxappts) --k; for (; k > j; k--) /* move everything up */ strcpy(lln[k], lln[k-1]); break; } else if (day == 100) dy = dy-100; /* reached new month */ if (j == maxappts) return NULL; return lln[j]; } /*=========================================================================== * specialdays() * find the file CAL.DAT and attempt to read in special date descriptions. * e.g. -999 12 25 00 Christmas Day * Yes, this is a spaghetti-code patch on top of a rather elegant calander * display program. Good luck understanding it; it's a mess, but it works. *=========================================================================*/ short specialdays(short m, short y) { FILE *fp; short mo, dy, yr, w, n, filenum, wn, weeklyflag, periodflag = 0, k, j, hiappt = 1, hilight = (m == thismonth && y == thisyear); char **lln = NULL, *ll; char str[MAXLINE]; if ((lln = (char **)calloc(maxappts+1, sizeof(char *)))==NULL) goto spcldone; if (m != thismonth) discard_old = 0; /* Special day descriptions are copied directly into line * buffer, at an offset of MonthWid. */ for (j = 0; j < maxappts; j++) lln[j] = &line[j][MonthWid-1]; strcpy(lln[0], " 100"); /* last (hiappt) entry */ for (filenum = 0; filenum < numfiles; filenum++) { if ((fp = efopen(filename[filenum], "r")) == NULL) continue; while (fgets(str, sizeof(str), fp) != NULL) { /* go until EOF is hit */ if (!isdigit(*str) && *str != '-') continue; /* a data line? */ if ((yr = atoi(str)) == 0) continue; /* get year */ if ((mo = atoi(&str[5])) == 0) continue; /* get month */ dy = atoi(&str[8]); /* get day */ wn = atoi(&str[11]); /*nth wkdy or period*/ /* Must have either day or weekday set */ if (!dy && !wn) continue; /* Currently, don't support periodically-recurring dates * that occur in next month/year. The following stops * that processing from happening. */ if (yr == y && mo > m && dy > 0 && wn > 0) continue; /* If currenty entry is a periodically-recurring date then * continue processing. * If current entry is for every year or current year, and * the month is for this month, continue processing. * If this month is december and the year is for every * year or next year, then continue processing if entry * is for january of next year. */ if (!( (yr >= 1970 && mo > 0 && dy > 0 && wn > 0) || ((yr == -999 || yr == y) && (mo == m || mo == m+1)) || /* got it all? */ ((yr == -999 || yr == y+1) && (mo == 1 && m == 12)) || mo == -9)) continue; /* Check for daily reminders and force entry to look like * it happens today as long as we are displaying a calendar * for the real this month and this year. */ if (dy == -9) { if (m == thismonth && y == thisyear) dy = thisday; /* set daily reminder */ else continue; } /* Skip entries that are not for month to be displayed if user * request that. */ if (discard_old == 2 && mo != thismonth && dy != thisday && yr != thisyear) continue; periodduplicate: if (yr >= 1970 && mo > 0 && dy > 0 && wn > 0 /* proper format? */ && !(yr == thisyear && mo == thismonth && dy == thisday && !periodflag) /* not today? */ && yr <= y && !(yr == y && mo > m)) { /* <= displayed month & year? */ while (yr < y || mo <= m) { /* find periodic dates */ add_days(&yr, &mo, &dy, wn); if (yr == y && mo == m) break; } if (mo > m) continue; /* periodic dates left in month */ periodflag = (days[m] - dy)/wn; if (periodflag && ((discard_old && dy 0 && mo > 0 && dy > 0) && ((wn >= 11 && wn <= 57) || w == 9) && (mo == m || mo == -9)) { /* find nth weekday */ n = wn%10 - 1; /* day of week (0=sun, 1=mon, etc.) */ if (n < 0 || n > 6) continue; if ((dy = nth_weekday(y,m,w,n)) < 0) { if (--weeklyflag > 0) goto weeklyduplicate; else continue; /* nth weekday didn't exist */ } } if (!dy || (mo > 0 && dy > days[mo])) continue; /* next loop if wn>57 or wn<11 or dy=0 */ if ((mo == m+1 && (yr == y || yr == -999)) || (mo == 1 && m == 12 && (yr == y+1 || yr == -999))) dy += 100; /* make sure 'next month' days are last */ if ((discard_old && dy= 100) continue; if ((ll = insertitem(lln,hiappt,dy)) == NULL) continue; ll[0] = (hilight && dy == thisday && (mo == m || mo == -9)) ? '*' : ' '; /* 'today' flag */ ll[1] = (dy%100 < 10) ? ' ' : '0' + (dy%100)/10; ll[2] = '0' + dy%10; ll[3] = ':'; j = strlen(str) - 1; /* get rid of trailing white space */ while (j >= 13 && isspace(str[j])) str[j--] = '\0'; /*=========================================================================== * Check for special case of Anniversary/Birthdays * Change added by R. Scott, and generalized a bit by Alex Matulich * A field indicated by [] will be displayed with [], but a field using {} * will be displayed without the braces. *=========================================================================== * These changes replace the next two lines: * str[j = 14+DAY_DESC-6] = '\0'; * strcpy(&ll[4], &str[13]); *===========================================*/ j=13; k=4; /* init pointers into strings */ while (k < DAY_DESC - 1 && str[j]) { ll[k++] = str[j]; if (str[j] == '\\') { /* Don't treat next char as special */ ll[k-1] = str[++j]; /* Write next char over '\' */ j++; /* & then advance to next char */ } /* start of [field] */ else if (str[j] == '[' || str[j] == '{') { short suffix = -1; /* <0 indicates no ordinal suffix */ long ipower = 1, by = atoi(&str[++j]); /* year of aniversary */ if (by <= y) { /* will year be modified? */ by = y - by + (dy>100 && mo==1); /* years since anniversary */ if (str[j-1] == '{') suffix = by; /* ordinal suffix will be attached */ } if (str[j-1] == '{' || str[j-1] == '[') --k; /* don't display brace */ while (by / ipower) ipower *= 10L; ipower /= 10L; /* ipower is now the magnitude of by */ if (!by) ll[k++] = '0'; else while (ipower && k < DAY_DESC - 1) { ll[k++] = by / ipower + '0'; by -= (by / ipower) * ipower;/* remove largest digit */ ipower /= 10L; } /* optionally add the ordinal suffixes st, nd, rd and th * to the end of value for better readability (for example, * 31 will be 31st, 23 will be 23rd, etc.) */ if (suffix >= 0 && k < DAY_DESC - 3) { suffix %= 100; /* only use last two digits */ if (suffix >= 11 && suffix <= 13) suffix = 4; else suffix %= 10; /* last digit */ switch (suffix) { case 1: ll[k++]='s'; ll[k++]='t'; break; case 2: ll[k++]='n'; ll[k++]='d'; break; case 3: ll[k++]='r'; ll[k++]='d'; break; default: ll[k++]='t'; ll[k++]='h'; } } while (isdigit(str[j])) ++j; /* advance to end of field */ if (str[j] == '}' || str[j] == ']') ++j; /* skip brace*/ } else ++j; /* advance to next char */ } ll[k] = '\0'; /* ensure string is terminated */ /*=========================================================================== * End of anniversary changes *=========================================================================*/ if (++hiappt > maxappts) hiappt = maxappts; if (--weeklyflag > 0) goto weeklyduplicate; /* dup. wkly reminders */ if (periodflag > 0) goto periodduplicate; /* dup. periodic reminders */ } fclose(fp); } for (j = 0; j < hiappt; j++) if (atoi(&lln[j][1]) == 100) break; /* find last item */ if (j == hiappt-1) lln[--hiappt][0] = '\0'; else if (j < hiappt) strcat(strcat(strcpy(lln[j], " "), months[(m%12)+1]), "--"); spcldone: free(lln); return hiappt; } #ifdef USE_REMINDER /* dayofweek() * convert Sun, Mon, Tues, etc. to number (honours europe flag) * returns 0 in case of error */ int dayofweek(const char *day) { switch (toupper(day[0])) { case 'S': if (tolower(day[1]) == 'u') return europe ? 7 : 1; else return 7 - europe; case 'M': return 2 - europe; case 'T': if (tolower(day[1]) == 'u') return 3 - europe; else return 5 - europe; case 'W': return 4 - europe; case 'F': return 6 - europe; default: return 0; } } /*=========================================================================== * reminderdays() * find the file DATES and attempt to read in reminder-style date descriptions. * e.g. 12/25:7:Christmas Day::N *=========================================================================*/ short reminderdays(short m, short y) { FILE *fp; short mo, dy, yr, n, wn, weeklyflag, filenum, j, hiappt = 1, hilight = (m == thismonth && y == thisyear); char **lln = NULL, *ll; char *descrip; static char tempstr[MAXLINE]; /* big enough for a long reminder line */ if (!data_file) return 0; /* don't read any data files */ if ((lln = (char **)calloc(maxappts+1, sizeof(char *)))==NULL) return 1; /* Special day descriptions are copied directly into line * buffer, at an offset of MonthWid. */ for (j = 0; j < maxappts; j++) lln[j] = &line[j][MonthWid-1]; strcpy(lln[0], " 100"); /* last entry */ if (m != thismonth) discard_old = 0; clearfilenames(); /* ignore all the cal native format data files */ addfilename(REMINDER_FILE); for (filenum = 0; filenum < numfiles; filenum++) { if ((fp = efopen(filename[filenum], "r")) == NULL) continue; /* go until EOF is hit */ while (fgets(tempstr, sizeof(tempstr), fp) != NULL) { if (isspace(tempstr[0])) continue; /* ignore blanks and empty lines */ else if (strchr(tempstr, ':') && (isdigit(tempstr[0]) || (tempstr[1] != ':'))) { /* assume normal date entry & not include file (which may be of form C:\NAME) */ char *field = strtok(tempstr, ":"); /* get date */ if (isdigit(field[0])) { mo = yr = wn = 0; /* day of month only? */ dy = atoi(tempstr); if ((field = strchr(field,'/')) != NULL) { /* mm/dd or mm/dd/yy format */ mo = dy; if (mo != m) /* not this month */ continue; dy = atoi(field+1); yr = 0; if ((field = strchr(field+1,'/')) != NULL) { /* mm/dd/yy format */ yr = atoi(field+1); if (yr < 1000) yr = yr + 1900; } } if ((dy > 31)) /* bad day */ continue; if (yr && (yr != y)) /* not this year */ continue; } else { /* day of week */ dy = mo = yr = 0; wn = dayofweek(field); } strtok(NULL, ":"); /* skip days of notice */ descrip = strtok(NULL, ":"); /* get description */ /* get person & status fields */ if ((field = strtok(NULL, "\n")) == NULL) continue; /* skip if sanity check fails */ if (field[0] != ':') { /* person is specified */ char *newdescrip = malloc(LineWid); field = strtok(field, ":"); /* get person */ strcat(strcat(strcpy(newdescrip, field), "'s "), descrip); /* BUG: could overwrite end by 1 char */ strcpy(descrip, newdescrip); field = strtok(NULL, ":"); /* get status */ free(newdescrip); } else ++field; if (!field || field[0] == 'D') /* do not report this event */ continue; } else { /* must be an include file--add to the list to check */ /* NOTE: this malloced storage is never freed */ addfilename(strtok(strcpy(malloc(strlen(tempstr)+1),tempstr),"\n")); continue; } weeklyflag = 5*(wn>0); /* flag to dup. weekly dates */ do { if (!(yr > 0 && mo > 0 && dy > 0) && (wn >= 1) && (mo == m || mo <= 0)) { n = wn - 1; /* day of week (0=sun, 1=mon, etc.) */ if ((dy = nth_weekday(y,m,weeklyflag,n)) < 0) { if (--weeklyflag > 0) continue; else continue; /* nth weekday didn't exist */ } } if (!dy) continue; /* ignore if dy=0 */ if (discard_old < 2 && ((mo == m+1 && (yr == y || yr <= 0)) || (mo == 1 && m == 12 && (yr == y+1 || yr <= 0)))) dy += 100; /* make sure 'next month' days are last */ if ((discard_old && dy 0 && isspace(descrip[j])) descrip[j--] = '\0'; descrip[DAY_DESC-5] = '\0'; /* truncate description */ strcpy(&ll[4], descrip); if (++hiappt > maxappts) hiappt = maxappts; } while (--weeklyflag > 0); /* dup. weekly reminders */ } fclose(fp); } for (j = 0; j < hiappt; j++) if (atoi(&lln[j][1]) == 100) break; /* find last item */ if (j == hiappt-1) lln[--hiappt][0] = '\0'; else if (j < hiappt) strcat(strcat(strcpy(lln[j], " "), months[m%12]), "--"); free(lln); return hiappt; } #endif /* USE_REMINDER */ /*=========================================================================== * efopen() - fopen() replacement that does path searches *=========================================================================*/ FILE *efopen(const char *file, const char *mode) { FILE *fp; char str[CAL_MAXPATH]; #ifdef OS2 char path[CAL_MAXPATH]; #endif /* OS2 */ /* Attempt to open file using exact name passed in */ if ((fp = fopen(file, mode)) == NULL) { /* If not found and we know the users home directory then * look there. Need to sanitize the filename though. */ if (*homedir && strlen(homedir) < CAL_MAXPATH) { strcpy(str, homedir); if ((strlen(homedir) + strlen(file) + 1) < CAL_MAXPATH) { #ifdef UNIX if (homedir[strlen(homedir)-1] != '/') strcat(str,"/"); if (file[0] != '.') strcat(str, "."); #else if (homedir[strlen(homedir)-1] != '/') strcat(str,"\\"); #endif strcat(str, file); fp = fopen(str, mode); } } #ifdef OS2 if (fp == NULL) { _searchenv(file, "PATH", path); if (*path == '\0') _searchenv(file, "DPATH", path); if (*path) fp = fopen(path, mode); } #endif /* OS2 */ /* If still not found then look in a hardcoded path */ if (fp == NULL) { #ifdef PREFIX strcpy(str, PREFIX); #else /* Note the unix style path; Under DOS/OS/2 you better * define PREFIX to prevent this from being used! */ strcpy(str, "/ect/cal/"); #endif if (strlen(str) + strlen(file) <= CAL_MAXPATH) { strcat(str,file); fp = fopen(str, mode); } } } return fp; } /*=========================================================================== * usage() - called from main() - display commandline usage *=========================================================================*/ void usage() { fputs("\n\ cal 4.0 - Display a monthly or yearly calendar, with optional appointments.\n\n\ Usages: cal [options] [[1|2|3|...|12] year]\n\ cal [options] [jan|feb|mar|...|dec] [year]\n\n\ Options:\n\ --3[months] Display prev/current/next month\n\ --a[ppts]=n Display maximum of n (8-50) appointments (24)\n\ --con[tinue]=n Display successive months n times after the first\n\ --d[ata-file]=file Load appointments from `file'\n\ (default: ",stderr); #ifdef PREFIX fputs(PREFIX, stderr); #else fputs("/etc/cal/", stderr); #endif #ifndef UNIX fputs("cal.dat)\n", stderr); #else fputs("cal.dat, $HOME/.cal.dat)\n", stderr); #endif fputs("\ --e[urope] European format (first day is Monday)\n\ --f[uture] Show only future appointments on current month\n\ --j[uian] Display Julian dates (days numbered from 1 January\n\ --m[onday] Display Monday as first day of week (same as --europe)\n\ --nod[ata] Ignore appointment descriptions file\n\ --p[ause] Pause for keystroke before exiting\n\ --th[ismonth] Show only current month appointments\n\ --to[day] Show only today's appointments on current month\n\ --y[ear] Display a calendar for the current year\n", stderr); #ifdef USE_COLOR fputs("\ --u[se-color] Allow use of colors\n\ --noc[olor] Inhibit the use of colors\n\ --col[or-file]=file Load color definitions from `file'\n\ (default: ",stderr); #ifdef PREFIX fputs(PREFIX, stderr); #else fputs("/etc/cal/", stderr); #endif #ifndef UNIX fputs("cal.col)\n", stderr); #else fputs("cal.col, $HOME/.cal.col)\n", stderr); #endif #endif /* USE_COLOR */ fputs("\n(c) 1992-2002 A. Matulich, Unicorn Research Corporation\n\ http://unicorn.us.com\n", stderr); } cal-4.0/src/makefile.unx0100644000076400007640000000130706750722022015352 0ustar cbagwellcbagwell# From: cbagwell@sprynet.com (Chris Bagwell) # Makefile for "cal" # # only tested with GNU gcc # To use, enter "make -f makefile.unx" # normal default DEFAULT_DATA_DIR="\"/files/home/ftp/pub/unicorn/pub/cal35/\"" #DEFAULT_DATA_DIR="\"/usr/lib/\"" RM=rm -f CC=gcc # Using -Wall will create some warnings on SunOS that can be ignored. # CFLAGS=-O2 -Wall -DUNIX -DUSE_REMINDER -DPREFIX=$(DEFAULT_DATA_DIR) CFLAGS=-O2 -Wall -DUNIX -DUSE_REMINDER BINDIR=/usr/bin MANDIR=/usr/man default: cal cal : cal.c $(CC) $(CFLAGS) -o cal cal.c cal.man : cal.1 nroff -man cal.1 | col > cal.man install: cal install -c -m 755 cal $(BINDIR)/cal install -c -m 644 cal.1 $(MANDIR)/man1/cal.1 clean: $(RM) cal cal-4.0/src/notes.os20100600000076400007640000000044705672766524014633 0ustar cbagwellcbagwellThe new (2.9) code to handle display widths wider than 80 columns has not been implemented in the OS/2 or bound executables. The Vio calls do not return the proper information in my tests on a paradise card in 132-column mode (see the VioSetMode docs in the on-line reference "prcp.inf"). cal-4.0/src/readme.os20100600000076400007640000000175606071271500014717 0ustar cbagwellcbagwellThis archive contains a port to OS/2 1.x--2.x of Matulich's cal 2.9a, which is an enhanced version of the UNIX cal (see cal.doc). Notes on files: ./ cal.exe Original DOS executable cal-os2.exe OS/2 1.x--2.x executable readme.os2 this file source/ cal.c unmodified source (Use "patch < patches.os2" for OS/2) cal.def linker definition file cal-32.def linker definition file for EMX version makefile.os2 makefile for EMX/gcc and MSC notes.os2 notes on this port Notes: 1. From readme.cal: This archived collection of files is placed into the Public Domain. Feel free to redistribute the this archive, but PLEASE make sure the archive contains all the original files [...] 2. The enclosed executable can be bound to produce a file which will run under both OS/2 and DOS (see makefile.os2). 3. The original DOS-only version can detect the display width. --Darrel Hankerson hankedr@mail.auburn.edu 25 July 1993