home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 February / PCWorld_2000-02_cd.bin / live / usr / X11R6 / bin / pscal < prev    next >
Text File  |  1997-10-12  |  13KB  |  638 lines

  1. #!/bin/sh
  2. #+
  3. #
  4. # NAME:
  5. #    pscal
  6. #
  7. # SYNOPSIS:
  8. #    pscal [-Pprinter] [other printer flags] month year
  9. #
  10. # DESCRIPTION:
  11. #    `Pscal' is a PostScript program to print calendars.
  12. #
  13. #    The file $HOME/.holiday is read and used to print short messages
  14. #    on specified days.  The .holiday file should consist of lines of
  15. #    the form 
  16. #        month:day:message string
  17. #    Messages should be 20 characters or less, with no more than 6
  18. #    messages per day.  No spaces should appear from the beginning
  19. #    of a line until after the second colon.
  20. #    Month and day should be numbers in the obvious ranges.
  21. #    12/89 - The holiday checking has been loosened up in that the
  22. #    following takes place:
  23. #        1. The Shell Variable EFILE is used preferentially
  24. #        2. Then the file Events in the current directory is used
  25. #        3. Finally the $HOME/.holiday file is used.
  26. #    The whole process can be turned off by setting EFILE=/dev/null.
  27. #
  28. # OPTIONS:
  29. #    Any argument whose first character is '-' is passed on to lpr.
  30. #    The shell variables BANNER, LFOOT, CFOOT, and RFOOT become a
  31. #    top centered banner, and left, centered, or right justified
  32. #    footers respectively.  As in:
  33. #
  34. #        BANNER="Schedule 1" CFOOT=Preliminary pscal 4 90
  35. #
  36. # AUTHOR:
  37. #    Patrick Wood
  38. #    Copyright (C) 1987 by Pipeline Associates, Inc.
  39. #    Permission is granted to modify and distribute this free of charge.
  40. # HISTORY:
  41. #    @Original From: patwood@unirot.UUCP (Patrick Wood)
  42. #    @Shell stuff added 3/9/87 by King Ables
  43. #    @Made pretty by tjt 1988
  44. #    @Holiday and printer flag passing hacks added Dec 1988 
  45. #    @ by smann@june.cs.washington.edu 
  46. #    @Used the better looking version with 5 rows of days rather than 6
  47. #    @ hacked together with holiday and banner/footnotes added
  48. #    @ by Joe (No Relation) Wood, 12/89, jlw@lzga.ATT.COM
  49. #    @Fixed "-R" (didn't work at all; now it at least works on 8.5x11)
  50. #    @Also fixed handling of unrecognized arguments
  51. #    @ by Jeff Mogul, 1/90, mogul@decwrl.dec.com
  52. #
  53. # BUGS:
  54. #    `Pscal' doesn't work for months before 1753 (weird stuff happened
  55. #    in September, 1752).
  56. #
  57. #    A better format for the dates of holidays would be nice.
  58. #    An escape to allow holiday messages to be raw PostScript would
  59. #    also be nice.
  60. #    The holiday messages should be handled more intelligently (ie,
  61. #    the messages should be clipped to the day).
  62. #
  63.  
  64. # PostScript program to print calendars.
  65. # Doesn't deal well with September 1752 or before.
  66.  
  67. USAGE="Usage: pscal [ -Rrt ] [ -F hfont ] [ -f font ] [-d directory] [ month [ year ] ]"
  68.  
  69. TFONT=Times-Bold
  70. DFONT=Helvetica-Bold
  71. EFONT=Times-Roman
  72.  
  73. Calendar=$HOME/Calendar
  74.  
  75. ROTATE=90
  76. SCALE="1.0 1.0"
  77. #    Was 50 -120 - changed to 71 -120 for A4 Use
  78. TRANSLATE="71 -120"
  79.  
  80. LPR="lpr"
  81.  
  82. while test $# != 0
  83. do
  84.     case $1 in
  85.     -P) test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
  86.         eval ENVAR="$1$2"; shift; shift;;
  87.     -P*) eval ENVAR=$1; shift;;
  88.     -F) test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
  89.         TFONT="$2"; shift; shift;;
  90.     -F*) TFONT=`echo $1 | sed -n 1s/-.//p`; shift;;
  91.     -f) test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
  92.         DFONT="$2"; shift; shift;;
  93.     -f*) DFONT=`echo $1 | sed -n 1s/-.//p`; shift;;
  94.     -t) LPR=cat; shift;;
  95.     -r) ROTATE=90; shift;;
  96.     -R) ROTATE=0; SCALE="0.75 0.75"; TRANSLATE="50 900"; shift;;
  97.     -d) test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
  98.         Calendar="$2"; shift; shift;;
  99.     --|-) break;;
  100.     -*) eval ENVAR=\"$ENVAR $1\"; shift;;
  101.     *) break
  102.     esac
  103. done
  104.  
  105. test $# -gt 2 && { echo "$USAGE" 1>&2; exit 1; }
  106.  
  107. case $# in
  108.     0)    set `date`; YEAR=$6; MONTH=$2;;
  109.     1)    MONTH=$1; set `date`; YEAR=$6;;
  110.     2)    MONTH=$1 YEAR=$2;;
  111. esac
  112.  
  113. MONTH=`case $MONTH in Jan|jan) echo 1;;Feb|feb) echo 2;;Mar|mar) echo 3;;Apr|apr) echo 4;;
  114.     May|may) echo 5;;Jun|jun) echo 6;;Jul|jul) echo 7;;Aug|aug) echo 8;;
  115.     Sep|sep) echo 9;;Oct|oct) echo 10;;Nov|nov) echo 11;;Dec|dec) echo 12;;
  116.     1|2|3|4|5|6|7|8|9|10|11|12) echo $MONTH;;esac`
  117.  
  118. MONTHNAME=`sed -n ${MONTH}p <<END-monthlist
  119. Jan
  120. Feb
  121. Mar
  122. Apr
  123. May
  124. Jun
  125. Jul
  126. Aug
  127. Sep
  128. Oct
  129. Nov
  130. Dec
  131. END-monthlist`
  132.  
  133. test $YEAR -lt 100 && YEAR=`expr $YEAR + 1900`
  134.  
  135. if [ -n "$EFILE" -a -r "$EFILE" ]
  136. then
  137.     Files=$EFILE
  138.     monthday=yes
  139. elif [ -r Events ]
  140. then
  141.     Files=Events
  142.     monthday=yes
  143. elif [ -r $HOME/.holiday ]
  144. then
  145.     Files=$HOME/.holiday
  146.     monthday=yes
  147. elif [ -d $Calendar ]
  148. then
  149.     cd $Calendar
  150.     if [ -d xy$YEAR ]
  151.     then
  152.         cd xy$YEAR
  153.     fi
  154.     list=`echo xc*$MONTHNAME$YEAR`
  155.     case "$list" in
  156.     xc\*$MONTHNAME$YEAR)
  157.             ;;
  158.     *)
  159.         for file in $list
  160.         do
  161.             day=`expr $file : 'xc\([0-9]*\)'`
  162.             (cat $file;echo) | sed '/^$/d
  163.                     s/^/./' | fmt -25 |
  164.                      sed -n "7q
  165.                     s/^\.//
  166.                     s/^/$day ( /
  167.                     s/\$/ )/
  168.                     p"
  169.         done > /tmp/pscal$$
  170.         holidays=`cat /tmp/pscal$$`
  171.         rm -f /tmp/pscal$$    
  172.     esac
  173. fi
  174.  
  175. case "$monthday" in
  176. yes)
  177.     holidays=`cat $Files | grep \^$MONTH: | awk -F: '{printf("%s ( %s",$2,$3);\
  178.         for(i = 4; i <= NF; i++) printf(":%s", $i);printf(")\n"); }'`
  179. esac
  180.  
  181. $LPR $ENVAR <<END-OF-CALENDAR
  182. %!
  183. % PostScript program to draw calendar
  184. % Copyright (C) 1987 by Pipeline Associates, Inc.
  185. % Permission is granted to modify and distribute this free of charge.
  186.  
  187. % The number after /month should be set to a number from 1 to 12.
  188. % The number after /year should be set to the year you want.
  189. % You can change the title and date fonts, if you want.
  190. % We figure out the rest.
  191. % This program won't produce valid calendars before 1800 due to the switch
  192. % from Julian to Gregorian calendars in September of 1752 wherever English
  193. % was spoken.
  194.  
  195. /month $MONTH def
  196. /year $YEAR def
  197. /titlefont /$TFONT def
  198. /dayfont /$DFONT def
  199. /eventfont /$EFONT def
  200. /holidays [ $holidays ] def
  201. /Bannerstring ($BANNER) def
  202. /Lfootstring ($LFOOT) def
  203. /Rfootstring ($RFOOT) def
  204. /Cfootstring ($CFOOT) def
  205.  
  206. % calendar names - change these if you don't speak english
  207. % "August", "April" and "February" could stand to be kerned even if you do
  208.  
  209. /month_names
  210. [ (January) (February) (March) (April) (May) (June) (July)
  211. (August) (September) (October) (November) (December) ]
  212. def
  213.  
  214. /day_names
  215. [ (Sunday) (Monday) (Tuesday) (Wednesday) (Thursday) (Friday) (Saturday) ]
  216. def
  217.  
  218. % layout parameters - you can change these, but things may not look nice
  219.  
  220. /daywidth 100 def
  221. /dayheight 95 def
  222.  
  223. /titlefontsize 48 def
  224. /weekdayfontsize 10 def
  225. /datefontsize 30 def
  226. /footfontsize 20 def
  227.  
  228. /topgridmarg 35 def
  229. /leftmarg 35 def
  230. /daytopmarg 10 def
  231. /dayleftmarg 5 def
  232.  
  233. % layout constants - don't change these, things probably won't work
  234.  
  235. /rows 5 def
  236. /subrows 6 def
  237.  
  238. % calendar constants - change these if you want a French revolutionary calendar
  239.  
  240. /days_week 7 def
  241.  
  242. /days_month [ 31 28 31 30 31 30 31 31 30 31 30 31 ] def
  243.  
  244. /isleap {                % is this a leap year?
  245.     year 4 mod 0 eq            % multiple of 4
  246.     year 100 mod 0 ne         % not century
  247.     year 1000 mod 0 eq or and    % unless it's a millenia
  248. } def
  249.  
  250. /ndays {                % number of days in this month
  251.     days_month month 1 sub get
  252.     month 2 eq            % February
  253.     isleap and
  254.     {
  255.         1 add
  256.     } if
  257. } def
  258.  
  259. /weekday {                % weekday (range 0-6) for integer date
  260.     days_week mod
  261. } def
  262.  
  263. /startday {                % starting day-of-week for this month
  264.     /off year 2000 sub def        % offset from start of "epoch"
  265.     off
  266.     off 4 idiv add            % number of leap years
  267.     off 100 idiv sub        % number of centuries
  268.     off 1000 idiv add        % number of millenia
  269.     6 add weekday days_week add     % offset from Jan 1 2000
  270.     /off exch def
  271.     1 1 month 1 sub {
  272.         /idx exch def
  273.         days_month idx 1 sub get
  274.         idx 2 eq
  275.         isleap and
  276.         {
  277.             1 add
  278.         } if
  279.         /off exch off add def
  280.     } for
  281.     off weekday            % 0--Sunday, 1--monday, etc.
  282. } def
  283.  
  284. /prtevent {        % event-string day prtevent
  285.             %  print out an event
  286.     /start startday def
  287.     /day 2 1 roll def
  288.     day start add 1 sub 7 mod daywidth mul
  289.     day start add 1 sub 7 div truncate dayheight neg mul 
  290.     -5 
  291.     numevents day start add get -10 mul add
  292.     numevents
  293.     day start add 
  294.     numevents day start add get 1 add
  295.     put
  296.     add moveto
  297.     show
  298. } def
  299.  
  300. /drawevents {        % read in a file full of events; print
  301.             %  the events for this month
  302.     /numevents
  303.     [0 0 0 0 0 0 0
  304.      0 0 0 0 0 0 0
  305.      0 0 0 0 0 0 0
  306.      0 0 0 0 0 0 0
  307.      0 0 0 0 0 0 0
  308.      0 0 0 0 0 0 0] def 
  309.      eventfont findfont 9 scalefont setfont
  310.      0 2 holidays length 2 sub {
  311.         dup
  312.         1 add holidays 2 1 roll get
  313.         2 1 roll holidays 2 1 roll get
  314.         prtevent
  315.     } for
  316.         
  317. } def
  318.  
  319. % ------------------------------------------------------------------------
  320.  
  321. /prtnum { 3 string cvs show } def
  322.  
  323. /center {                % center string in given width
  324.     /width exch def
  325.     /str exch def width str 
  326.     stringwidth pop sub 2 div 0 rmoveto str show
  327. } def
  328.  
  329. /centernum { exch 3 string cvs exch center } def
  330.  
  331. /drawgrid {                % draw calendar boxes
  332.     titlefont findfont weekdayfontsize scalefont setfont
  333.     currentpoint /y0 exch def /x0 exch def
  334.     0 1 days_week 1 sub {
  335.         submonth 0 eq
  336.         {
  337.             x0 y0 moveto
  338.             dup dup daywidth mul 40 rmoveto
  339.             day_names exch get
  340.             daywidth center
  341.         } if
  342.         x0 y0 moveto
  343.         daywidth mul topgridmarg rmoveto
  344.         1.0 setlinewidth
  345.         submonth 0 eq
  346.         {
  347.             /rowsused rows 1 sub def
  348.         }
  349.         {
  350.             /rowsused rows def
  351.         }
  352.         ifelse
  353.         0 1 rowsused {
  354.             gsave
  355.             daywidth 0 rlineto 
  356.             0 dayheight neg rlineto
  357.             daywidth neg 0 rlineto
  358.             closepath stroke
  359.             grestore
  360.             0 dayheight neg rmoveto
  361.         } for
  362.     } for
  363. } def
  364.  
  365. /drawnums {                % place day numbers on calendar
  366.     dayfont findfont datefontsize
  367.     submonth 0 ne
  368.     {
  369.         2.5 mul
  370.     } if scalefont setfont
  371.     /start startday def
  372.     /days ndays def
  373.     start daywidth mul dayleftmarg add daytopmarg rmoveto
  374.     submonth 0 ne
  375.     {
  376.         dayleftmarg neg dayheight -2 div rmoveto
  377.     } if
  378.     1 1 days {
  379.         /day exch def
  380.         gsave
  381.         day start add weekday 0 eq
  382.         {
  383.             submonth 0 eq
  384.             {
  385.                 .7 setgray
  386.             } if
  387.         } if
  388.         day start add weekday 1 eq
  389.         {
  390.             submonth 0 eq
  391.             {
  392.                 .7 setgray
  393.             } if
  394.         } if
  395.         submonth 0 eq
  396.         {
  397.             isdouble
  398.             {
  399.                 day prtdouble
  400.             }
  401.             {
  402.                 day prtnum
  403.             } ifelse
  404.         }
  405.         {
  406.             day daywidth centernum
  407.         } ifelse
  408.         grestore
  409.         day start add weekday 0 eq
  410.         {
  411.             currentpoint exch pop dayheight sub 0 exch moveto
  412.             submonth 0 eq
  413.             {
  414.                 dayleftmarg 0 rmoveto
  415.             } if
  416.         }
  417.         {
  418.             daywidth 0 rmoveto
  419.         } ifelse
  420.     } for
  421. } def
  422. /isdouble {                % overlay today with next/last week?
  423.     days start add rows days_week mul gt
  424.     {
  425.         day start add rows days_week mul gt
  426.         {
  427.             true true
  428.         }
  429.         {
  430.             day start add rows 1 sub days_week mul gt
  431.             day days_week add days le and
  432.             {
  433.                 false true
  434.             }
  435.             {
  436.                 false
  437.             } ifelse
  438.         } ifelse
  439.     }
  440.     {
  441.         false
  442.     } ifelse
  443. } def
  444.  
  445. /prtdouble {
  446.     gsave
  447.       dayfont findfont datefontsize 2 mul 3 div scalefont setfont
  448.       exch
  449.       {
  450.         (23/) stringwidth pop dayheight rmoveto
  451.         prtnum
  452.       }
  453.       {
  454.         0 datefontsize 5 div rmoveto
  455.         prtnum
  456.         0 datefontsize -5 div rmoveto
  457.         gsave
  458.           dayfont findfont datefontsize scalefont setfont
  459.           (/) show
  460.         grestore
  461.       } ifelse
  462.     grestore
  463. } def
  464.  
  465. /drawfill {                % place fill squares on calendar
  466.     /start startday def
  467.     /days ndays def
  468.     currentpoint /y0 exch def /x0 exch def
  469.     submonth 0 eq
  470.     {
  471.         usefirst
  472.         {
  473.             /fillstart 2 def
  474.         }
  475.         {
  476.             /fillstart 0 def
  477.         }
  478.         ifelse
  479.     }
  480.     {
  481.         /fillstart 0 def
  482.     }
  483.     ifelse
  484.     fillstart daywidth mul topgridmarg rmoveto
  485.     1.0 setlinewidth
  486.     fillstart 1 start 1 sub {
  487.         gsave
  488.         .9 setgray
  489.         daywidth 0 rlineto 
  490.         0 dayheight neg rlineto
  491.         daywidth neg 0 rlineto
  492.         closepath fill
  493.         grestore
  494.         daywidth 0 rmoveto
  495.     } for
  496.     x0 y0 moveto
  497.     submonth 0 ne
  498.     {
  499.         /lastday rows 1 add days_week mul def
  500.         days_week 1 sub daywidth mul -440 rmoveto
  501.     }
  502.     {
  503.         /lastday rows days_week mul 2 sub fillstart add def
  504.         days_week 3 sub fillstart add daywidth mul
  505.         -440 dayheight add rmoveto
  506.     } ifelse
  507.     lastday -1 ndays start 1 add add
  508.     {
  509.         /day exch def
  510.         gsave
  511.         .9 setgray
  512.         daywidth 0 rlineto 
  513.         0 dayheight neg rlineto
  514.         daywidth neg 0 rlineto
  515.         closepath fill
  516.         grestore
  517.         day weekday 1 eq
  518.         {
  519.             x0 y0 moveto
  520.             days_week 1 sub daywidth mul -440 dayheight add rmoveto
  521.         }
  522.         {
  523.             daywidth neg 0 rmoveto
  524.         } ifelse
  525.     } for
  526. } def
  527.  
  528. /usefirst {                % are last two boxes used by days?
  529.     start ndays add rows days_week mul 3 sub gt
  530.     start 2 ge and
  531.     
  532. } def
  533.  
  534. /calendar
  535. {
  536.     titlefont findfont titlefontsize scalefont setfont
  537.     0 60 moveto
  538.     /month_name month_names month 1 sub get def
  539.     month_name show
  540.     /yearstring year 10 string cvs def
  541.     daywidth days_week mul yearstring stringwidth pop sub 60 moveto
  542.     yearstring show
  543.  
  544.     eventflag {
  545.         % Show a centered Banner if any at the Top
  546.         daywidth days_week mul 2 div
  547.         Bannerstring stringwidth pop 2 div sub
  548.         60 moveto
  549.         Bannerstring show
  550.         % Show footnotes left-center-right
  551.         eventfont findfont footfontsize scalefont setfont
  552.         /bottomrow { dayheight rows mul 5 sub neg } def
  553.         0 bottomrow moveto
  554.         Lfootstring show
  555.         daywidth days_week mul Rfootstring stringwidth pop sub
  556.         bottomrow moveto
  557.         Rfootstring show
  558.         daywidth days_week mul Cfootstring stringwidth pop sub 2 div
  559.         bottomrow moveto
  560.         Cfootstring show
  561.         
  562.     } if
  563.  
  564.     0 -5 moveto
  565.     drawnums
  566.  
  567.     0 -5 moveto
  568.     drawfill
  569.  
  570.     eventflag {
  571.         0 0 moveto
  572.         drawevents
  573.     } if
  574.  
  575.     0 -5 moveto
  576.     drawgrid
  577. } def
  578.  
  579. /eventflag true def
  580.  
  581. $SCALE scale
  582. $ROTATE rotate
  583. $TRANSLATE translate
  584. /submonth 0 def
  585. calendar
  586. /eventflag false def
  587. month 1 sub 0 eq
  588. {
  589.     /lmonth 12 def
  590.     /lyear year 1 sub def
  591. }
  592. {
  593.     /lmonth month 1 sub def
  594.     /lyear year def
  595. } ifelse
  596. month 1 add 13 eq
  597. {
  598.     /nmonth 1 def
  599.     /nyear year 1 add def
  600. {
  601.     /nmonth month 1 add def
  602.     /nyear year def
  603. } ifelse
  604. usefirst
  605. {
  606.     0 30 translate
  607. }
  608. {
  609.     days_week 2 sub daywidth mul -350 translate
  610. }
  611. ifelse
  612. /submonth 1 def
  613. /year lyear def
  614. /month lmonth def
  615. gsave
  616. .138 .138 scale
  617. 12 -120 translate
  618. calendar
  619. grestore
  620. /submonth 1 def
  621. /year nyear def
  622. /month nmonth def
  623. daywidth 0 translate
  624. gsave
  625. .138 .138 scale
  626. 12 -120 translate
  627. calendar
  628. grestore
  629.  
  630. showpage
  631.  
  632. END-OF-CALENDAR
  633.  
  634.